题目:
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
Example 1:
Input: word1 = "horse", word2 = "ros" Output: 3 Explanation: horse -> rorse (replace 'h' with 'r') rorse -> rose (remove 'r') rose -> ros (remove 'e')
Example 2:
Input: word1 = "intention", word2 = "execution" Output: 5 Explanation: intention -> inention (remove 't') inention -> enention (replace 'i' with 'e') enention -> exention (replace 'n' with 'x') exention -> exection (replace 'n' with 'c') exection -> execution (insert 'u')
此题我只知道用dp实现,其它的方法没有想到:
有两个单词 word1 word2
一、每一个都增加一个字母的话,如果增加的字母是一样的,那操作数P应该和没增加之前是一样的。
if(word[i] == word[j]){
P[i+1][j+1] == P[i][j];
}
二、如果增加的字母是不一样的,就有三个增加方式, 找出这三个最小值;
1. (word1增加单词,word2不增加单词) +1
比如word1:zg,word2:zght
word1增加一个t,这时最小操作数为1了,word2不管增加什么单词都要+1
这里的P[i+1][j]的意思是word1增加单词的最小操作数。
P[i+1][j+1] = P[i+1][j] + 1;
2.(word1不增加单词,word2增加单词 P[i+1][j]) + 1
比如word1:nihao,word2:niha
word2增加一个o,这时最小操作数为0了,word1不管增加什么单词都要+1
这里的P[i][j+1]的意思是word2增加单词的最小操作数。
P[i+1][j+1] = P[i][j+1] + 1;
3.word1不增加单词,word2不增加单词 P[i][j] + 1
这个就比较容易理解了,比如有这样的单词word1:td word2:sv
word1增加m word2增加n
这时P[i+1][j] = 3, P[i][j+1] = 3,而P[i][j] = 2;
所以:
if(word[i] != word[j]){
P[i+1][j+1] == min{P[i][j], P[i+1][j] ,P[i][j+1]} + 1;
}
三、动态规划一般都会有初始参数
比如word1=”xxxxxxxxx”, word2=””;操作数就是word1的长度,反过来也是一样。(仔细观察,word1变成word2的操作数一定是和word2变成word1的操作数是一样的,因为加的反是减,替换的反还是替换)
故:P[0][j] = j; P[i][0] = i;
实现就简单了,我这个人喜欢逆着来,所以这就是我的算法:
public static int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] point = new int[n + 1][m + 1];
for (int j = m; j >= 0; j--) {
point[n][j] = m - j;
}
for (int i = n; i >= 0; i--) {
point[i][m] = n - i;
}
for (int i = n - 1; i >= 0; i--) {
for (int j = m - 1; j >= 0; j--) {
if (word2.charAt(i) == word1.charAt(j)) {
point[i][j] = point[i + 1][j + 1];
} else {
point[i][j] = min(point[i + 1][j + 1], point[i][j + 1], point[i + 1][j]) + 1;
}
}
}
return point[0][0];
}
private static int min(int i, int j, int k) {
return i < j ? (i < k ? i : k) : (j < k ? j : k);
}