继续dp入门之旅
题目描述
虽然是二维dp的基础题,但在思路已经白嫖的情况下还是很久才理解实在是太菜了
思路
- dp含义
二维数组dp[i][j]表示word1的前i个字符转化成word2的前j个字符所需要的最少操作次数 - dp方程
在dp方程这点的理解上面还不够清晰,希望这次能彻底记住,
dp方程的意义就是通过子回答与当前回答关系得到答案---------这题可以分成两种大情况,
- 当我们发现word1[i] == word2[j] 时,这时候经过dp[i - 1][j - 1]次操作,word1的前i-1个字符转化成word2的1前j-1个字符,并且无需再进行任何操作
即dp[i][j] = dp[i - 1][j - 1] - 当我们发现word[i] != word2[j]时,有三种策略
- 删除字符
是在dp[i - 1][j]即word1的前i-1个字符已经转化成word2的前j个字符的情况下,删除word1[i]
即dp[i] [j] = dp[i - 1] [j] + 1; - 增加字符
是在dp[i][j-1]即word1的前i个字符已经转化成word2的前j-1个字符的情况下,增加word1[i]=word[j]
即dp[i] [j] = dp[i] [j - 1] + 1; - 改变字符
是在dp[i - 1][j - 1]即word1的前i-1个字符已经转化成word2的前j-1个字符的情况下,改变 word1[i]=word[j]
即dp[i] [j] = dp[i - 1] [j - 1] + 1;**
综上,dp方程为
- 删除字符
word1[i] == word2[j]
dp[i][j] = dp[i - 1][j - 1]
word1[i] != word2[j]
dp[i] [j] = min(dp[i - 1] [j - 1],dp[i] [j - 1],dp[[i - 1] [j]) + 1;
- 初始值
很明显数组的i坐标为0和j坐标为0的一系列点无法通过dp方程得到;知道他们的值并不难:
dp[0][n] (n∈N) 需要word1进行n次增加字符操作
dp[n][0] (n∈N) 需要word1进行n次删除字符操作
即 dp[0][n] = n; dp[n][0] = n;
得到代码
class Solution {
public:
int minDistance(string word1, string word2) {
int wordLen1 = word1.size();
int wordLen2 = word2.size();
vector<vector<int>> dp (wordLen1 + 1, vector<int>(wordLen2 + 1, 0));
for(int i = 0; i <= wordLen2; i ++) dp[0][i] = i;
for(int j = 0; j <= wordLen1 ; j ++) dp[j][0] = j;
for(int i = 1 ; i <= wordLen1 ; i ++)
for(int j = 1; j <= wordLen2 ; j++) {
if(word1[i - 1] == word2[j - 1])//这里有坑,要注意word的下标从0开始,dp的下标从1开始
dp[i][j] = dp[i - 1][j - 1];
else dp[i][j] = min(min(dp[i - 1][j - 1], dp[i -1][j] ), dp[i][j - 1]) + 1;
}
return dp[wordLen1][wordLen2];
}
};
现在只能勉勉强强写出dp,优化子结构还得继续学习。