题目
Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.
You have the following 3 operations permitted on a word:
- Insert a character
- Delete a character
- Replace a character
我的想法
如果是自顶向下,每一步操作,都是在之前的最小步数上+1,但是怎样求得第一步该怎么走。如果是自底向上,又该怎样定义子问题?太难了,做不出
解答
其实现在感觉也还是似懂非懂,不知道为什么可以想到用这种方式进行存储
leetcode solution 1: DP-Bottom up
这里只是求需要的步数,因此并不需要考虑这个操作到底是删除还是插入或改变。
cost[i][j]
表示的是使word1
的前i
个字符与word2
的前j
个字符相同所需要的代价。比如w1 = abcde, w2 = abdef
,cost[4][2]
就等于使abcd
变成ab
需要的最少操作,即删掉2个字符,因此为2
有三种情况
word1[i] == word2[j]
两者相等,则无需任何操作,因此cost[i][j] = cost[i - 1][j - 1]
- word1[i] != word2[j]
两者若不等,则进行操作- 插入,则
cost[i][j] = cost[i][j - 1] + 1
。比如ros, ross
在i = 2, j = 3
时插入,cost[i][j - 1] + 1 -> cost[2][2] + 1
。只有在i < j
时,插入才有意义 - 删除,把
i
处的字符删掉,此时的cost[i][j] = cost[i - 1][j] + 1
。只有在i > j
时,删除才有意义 - 修改,因为字符数并没有发生改变,则
cost[i][j] = cost[i - 1][j - 1] + 1
- 插入,则
- 边界情况
cost[k][0] = cost[0][k] = k
,即最少需要k次插入或者删除
public class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] cost = new int[m + 1][n + 1];
for(int i = 0; i <= m; i++)
cost[i][0] = i;
for(int i = 1; i <= n; i++)
cost[0][i] = i;
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
if(word1.charAt(i-1) == word2.charAt(j-1))
cost[i][j] = cost[i - 1][j - 1];
else {
int a = cost[i - 1][j - 1];
int b = cost[i - 1][j];
int c = cost[i][j - 1];
cost[i][j] = Math.min(a,Math.min(b,c));
cost[i][j]++;
}
}
}
return cost[m][n];
}
}
leetcode solution 2: DP-Bottom up optimization
改进版,速度快了一倍
public class Solution {
public int minDistance(String word1, String word2) {
int[] strg = new int[word2.length() + 1];
for(int i = word1.length();i >= 0;i--){
int save = 0;
for(int j = word2.length();j >= 0;j--){
if(i == word1.length()){
strg[j] = word2.length() - j;
continue;
}
if(j == word2.length()){
save = strg[j];
strg[j] = word1.length() - i;
continue;
}
if(word1.charAt(i) == word2.charAt(j)){
int temp = save;
save = strg[j];
strg[j] = temp;
}else{
int insert = strg[j + 1];
int delete = strg[j];
int replace = save;
save = strg[j];
strg[j] = Math.min(insert, Math.min(delete, replace)) + 1;
}
}
}
return strg[0];
}
}
leetcode solution 3: DP-Top down
public class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m+1][n+1];
return editDist(dp, word1, word2, m, n);
}
private int editDist(int[][] dp, String str1 , String str2 , int m ,int n){
int result;
if(dp[m][n] !=0) return dp[m][n];
if(m==0) return n;
if(n==0) return m;
if (str1.charAt(m-1) == str2.charAt(n-1)) {
result= editDist(dp, str1, str2, m-1, n-1);
}
else{
result = 1 + Math.min(
Math.min(editDist(dp, str1, str2, m, n-1), // Insert
editDist(dp, str1, str2, m-1, n)), // Remove
editDist(dp, str1, str2, m-1, n-1)); // Replace
}
dp [m][n] =result;
return result;
}
}