1、dp[i][j] 的定义
以i-1 结尾的word1 和 以 j-1结尾的word2想要达到相等,所需要删除元素的最少次数。
2、递推公式
如果 i-1 == j-1 那么dp[i][j] = dp[i-1][j-1]
如果 i-1 != j-1 那么dp[i][j]就会有三种选择
dp[i-1][j-1] + 2
dp[i-1][j] + 1
dp[i][j-1] + 1
其中 dp[i-1][j-1] + 2 和 dp[i][j - 1] + 1 是一样的,相当于在j-1的基础上i再退一步。
所以dp[i][j] = min(dp[i-1][j] + 1,dp[i][j-1] + 1)。
3.初始化
dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。
dp[0][j]的话同理
4、遍历顺序显然是从上到下,从左到右
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
for(int i = 0; i <= word1.size(); ++i) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
for(int i = 1; i<=word1.size();++i){
for(int j = 1; j <= word2.size();++j){
if(word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1];
else{
dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1);
}
}
}
return dp[word1.size()][word2.size()];
}
};
1. 确定dp数组(dp table)以及下标的含义
dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
2. 确定递推公式
if (word1[i - 1] == word2[j - 1])
不操作
if (word1[i - 1] != word2[j - 1])
增
删
换
1、if (word1[i - 1] == word2[j - 1]) 那么说明不用任何编辑,dp[i][j] 就应该是 dp[i - 1][j - 1],即dp[i][j] = dp[i - 1][j - 1];
2、if (word1[i - 1] != word2[j - 1]),此时就需要编辑了
操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。即 dp[i][j] = dp[i - 1][j] + 1;
操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。即 dp[i][j] = dp[i][j - 1] + 1;
3、word2添加一个元素,相当于word1删除一个元素,
4、替换元素,word1替换word1[i - 1],使其与word2[j - 1]相同,此时不用增删加元素。那么只需要一次替换的操作,就可以让 word1[i - 1] 和 word2[j - 1] 相同。
所以 dp[i][j] = dp[i - 1][j - 1] + 1;
综上,当 if (word1[i - 1] != word2[j - 1]) 时取最小的,即:dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
3. dp数组如何初始化
再回顾一下dp[i][j]的定义:
dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
那么dp[i][0] 和 dp[0][j] 表示什么呢?
dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。
那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i;
同理dp[0][j] = j;
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
for(int i = 0; i <= word1.size();++i) dp[i][0] = i;
for(int j = 0; j <= word2.size();++j) dp[0][j] = j;
for(int i = 1; i <= word1.size();++i){
for(int j = 1; j <= word2.size();++j) {
if(word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1];
else{
dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]})+1;
}
}
}
return dp[word1.size()][word2.size()];
}
};