leetcode hot100:十三、解题思路大全:多维动态规划(不同路径、最小路径和、最长回文子串、 最长公共子序列、编辑距离)
不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
提示:
- 1 <= m, n <= 100
- 题目数据保证答案小于等于 2 * 109
思路
为什么会考虑用纯dp做,而不是回溯或者dfs或者bfs。
因为如果用回溯/DFS/BFS来做的话,每次移动有 2 种选择(右 / 下),总路径数为组合数 C(m+n-2, m-1)。当m和n达到20左右时,就可能导致栈溢出或超时了。而这道题的m和n可以达到100的量级。
为什么是这个组合数呢?因为从 (0,0) 到 (m-1, n-1),机器人需要向右移动 (m-1) 次,向下移动 (n-1) 次,总移动次数为 (m-1)+(n-1) = m+n-2 次,其中向右移动m-1次,所以组合数为C(m+n-2, m-1)。
为此我们考虑dp,dp[i][j] 表示到达 (i,j) 的路径数。最后返回dp[-1][-1]即可。
最小路径和
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
思路
也是dp[i][j]表示从左上角达到(i,j)的最小数字总和。
最长回文子串
给你一个字符串 s,找到 s 中最长的 回文 子串。
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母组成
思路
这道题可以用dp做,也可以用贪心做。
贪心的做法是,对于每个位置i,尝试寻找以i结尾的最长回文子串,若找到,则更新。若没找到,则i++。时间复杂度为O(n^2)
dp做就是,设 dp[i][j] 表示字符串 s 从索引 i 到 j(闭区间)的子串是否为回文子串。
状态值:dp[i][j] = True 表示子串 s[i…j] 是回文,False 则不是。
目标:找到所有 dp[i][j] = True 的子串中长度最长的,记录其起始位置和长度。
时间复杂度也是O(n^2)
最长公共子序列
给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
思路
dp[i][j]表示考虑到text1[i-1]和text2[j-1]结尾的最长公共子序列的长度
编辑距离
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
思路
dp[i][j]就是以word1[i-1]为结尾的字符串转化到以word2[j-1]为结尾的字符串所用的最少操作数。
伪代码如下:
if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]
else:"""dp[i-1][j]+1就是在word1结尾进行删除dp[i][j-1]+1就是在word1结尾进行添加dp[i-1][j-1]+1就是在word1结尾进行替换"""dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])+1