问题
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
例子
abc bad
3
分析
最优化问题 + 大问题可以用小问题来解决 => 动态规划
状态表
dp[i][j] word1[0, i-1]转化为word2[0, j-1]的最小步数初始状态
dp[0][0] = 0 空串=空串,不需要转化;
dp[i][0] = i, i >= 1 长度为i的字符串转化为空串,需要添加i个字符串;
dp[0][j] = j, j >= 1 空串转化为长度为j的字符串,需要删除i个字符串。状态转移方程
dp[i][j] = dp[i - 1][j - 1], if word1[i - 1] == word2[j - 1]
注:当word1的第i个字符和word2的第j个字符相等时, word1[0, i-1]转化为word2[0, j-1]的最小步数等于word1[0, i-2]转化为word2[0, j-2]的最小步数
dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1, if word1[i - 1] != word2[j - 1]
注:当word1的第i个字符和word2的第j个字符不相等时,word1可以先转换、删除第i个字符,或者在word2添加第j个字符,然后再进一步转化为word2。第一步都需要1次转化,第二步分别需要dp[i - 1][j - 1]、dp[i - 1][j]和dp[i][j - 1]次转化。取最小值即可。
要点
dp
时间复杂度
O(mn)
空间复杂度
O(mn)
代码
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; i++)
dp[i][0] = i;
for (int j = 1; j <= n; j++)
dp[0][j] = j;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; 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], min(dp[i - 1][j], dp[i][j - 1])) + 1;
}
}
return dp[m][n];
}
};
空间复杂度为O(2n)的代码
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
vector<vector<int>> dp(2, vector<int>(n + 1, 0));
for (int j = 1; j <= n; j++)
dp[0][j] = j;
int flag = 0;
for (int i = 1; i <= m; i++) {
dp[!flag][0] = i;
for (int j = 1; j <= n; j++) {
if (word1[i - 1] == word2[j - 1]) dp[!flag][j] = dp[flag][j - 1];
else dp[!flag][j] = min(dp[flag][j - 1], min(dp[flag][j], dp[!flag][j - 1])) + 1;
}
flag = !flag;
}
return dp[flag][n];
}
};
空间复杂度为O(n)的代码
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
vector<int> dp(n + 1, 0);
for (int j = 1; j <= n; j++)
dp[j] = j;
for (int i = 1; i <= m; i++) {
int pre = dp[0];
dp[0] = i;
for (int j = 1; j <= n; j++) {
int temp = dp[j];
if (word1[i - 1] == word2[j - 1]) dp[j] = pre;
else dp[j] = min(pre, min(dp[j], dp[j - 1])) + 1;
pre = temp;
}
}
return dp[n];
}
};