题目描述
对于两个只含有小写英文字母(’a’-‘z’)的单词word1和word2,你可以对word1进行以下3种操作:
1) 插入一个字母;
2) 删除一个字母;
3) 替换一个字母.
请计算将word1变换成word2的最少操作数.
word1和word2的长度均不大于1000.
请为下面的Solution类实现解决上述问题的函数minDistance,函数的参数word1和word2为给出的两个单词,返回值为所求最少操作数.
class Solution {
public:
int minDistance(string word1, string word2) {
}
};
例1:word1 = “sunny”, word2 = “snowy”,返回值为3。
例2:word1 = “abc”, word2 = “ac”,返回值为1.
注意:你只需要提交Solution类的代码,你在本地可以编写main函数测试程序,但不需要提交main函数的代码. 注意不要修改类和函数的名称.
解题思路
经典动规。
使用一个二维数组dp[m][n]
来维护状态,它表示从一个长度为m的word1变换到一个长度为n的word2所需要的最少操作数。
每次将两个单词往前看一个字母,那么有如下两种可能。
- 两个字母相同。那么,显然不需要做更改操作,有
dp[m][n] = dp[m - 1][n - 1]
- 两个字母不相同,那么,需要考虑如下三种操作:
- 如果word1的当前字母和word2的前一个字母相同,那么说明word1需要做1次插入操作,即
dp[m][n] = 1 + dp[m][n - 1]
; - 如果word1的前一个字母和word2的当前字母相同,那么说明word1需要做1次删除操作,即
dp[m][n] = 1 + dp[m - 1][n]
; - 如果word1的前一个字母和word2的前一个字母相同,那么说明word1需要做1次替换操作,即
dp[m][n] = 1 + dp[m - 1][n]
.
- 如果word1的当前字母和word2的前一个字母相同,那么说明word1需要做1次插入操作,即
由于要找的是最小的操作次数,所以,在第二种情况下,取三种子情况的最小值。
AC代码
// Problem#: 20622
// Submission#: 5148871
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
class Solution {
public:
int triMin(int a, int b, int c) {
int tempA = min(a, b);
int tempB = min(b, c);
return min(tempA, tempB);
}
int minDistance(string word1, string word2) {
int m = word1.size();
int n = word2.size();
int dp[m + 1][n + 1];
for (int i = 0; i <= m; ++i) {
for (int j = 0; j <= n; ++j) {
if (i == 0) dp[i][j] = j;
else if (j == 0) dp[i][j] = i;
else if (word1[i - 1] == word2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = 1 + triMin(dp[i][j - 1], // insert
dp[i - 1][j], // remove
dp[i - 1][j - 1]); // replace
}
}
return dp[m][n];
}
};