一、 题目
这道题是求一个字符串编辑成为另一个字符串的最少操作数,只有三种操作包括添加,删除或者替换一个字符。
二、 分析
这其实是一道二维动态规划的题目,维护的变量dp[i][j]表示的是word1的前i个字符和word2的前j个字符编辑的最少操作数是多少。我们分两种情况来讨论:
1)如果word1[i-1]=word2[j-1],也就是当前两个字符相同,那么也就是不需要编辑,则我们容易得到dp[i][j]=dp[i-1][j-1]
2)如果word1[i-1]!=word2[j-1],那么我们就需要考虑三种操作,如果是插入word1,那么dp[i][j]=dp[i-1][j]+1,也就是取word1前i-1个字符和word2前j个字符的最好结果,然后添加一个插入操作;如果是插入word2,那么dp[i][j]=dp[i][j-1]+1,同上面一种操作;如果是替换操作,那么类似于上面第一种情况,但是要加一个替换操作(因为word1[i-1]和word2[j-1]不相等),所以递推式是dp[i][j]=dp[i-1][j-1]+1。
上面列举的情况包含了所有可能性,在网上看到有人可能会说为什么没有删除操作,其实这里添加一个插入操作永远能得到与一个删除操作相同的效果,所以删除不会使最少操作数变得更好,因此如果我们是正向考虑,则不需要删除操作。取上面几种情况最小的操作数,即为第二种情况的结果,即dp[i][j] = min(dp[i-1][j], res[i][j-1], dp[i-1][j-1])+1。
分析下复杂度,算法时间上就是两层循环,所以时间复杂度是O(m*n)。
class Solution {
public:
int minDistance(string word1, string word2) {
int len1 = word1.size();
int len2 = word2.size();
if(len1 == 0) return len2;
if(len2 == 0) return len1;
int dp[len1+1][len2+2];
//memset(dp,0,len1*len2*dp[0][0]);
for(int i=0;i<len1;i++)
for(int j=0;j<len2;j++)
dp[i][j] = 0;
for(int i=0; i<=len1; i++)
dp[i][0] = i;
for(int j=0; j<=len2; j++)
dp[0][j] = j;
for(int i=1; i<=len1; i++){
for(int j=1;j<=len2; j++){
if(word1[i-1] == word2[j-1])
dp[i][j] = dp[i-1][j-1];
else
dp[i][j] = 1 + Min(dp[i-1][j-1],Min(dp[i-1][j],dp[i][j-1]));
}
}
return dp[len1][len2];
}
int Min(int a, int b)
{
if(a>b)
return b;
else
return a;
}
};