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
这道题本来倒是一看就觉得应该是DP,因为有两个串,所以很自然地想用一个二维数组来保存中间结构,即用min[i][j]来表示word1[0...i]和word2[0...j]的最小edit distance.
进行递推求解的时候,初始是需要知道,min[i][0]和min[0][i]的值的,这个好算。不过注意当出现word1[i]=word2[0]或者word2[i] == word1[0]时有少许不同。比如word1="bbab",word2="a",那么min[0][0]=1,min[1][0]=2,min[2][0]=2,min[3][0]=3;
dp的公式如下:
min[i][j] = min[i-1][j-1], if word1[i] == word2[j];
= min{min[i-1][j-1], min[i - 1][j], min[i][j - 1]}, else; //对应于三种情况(插入、删除、替换)
代码如下:
1 class Solution { 2 public: 3 int minDistance(string word1, string word2) { 4 int n1 = word1.length(); 5 int n2 = word2.length(); 6 if (n1 == 0) return n2; 7 if (n2 == 0) return n1; 8 vector<vector<int> > min(n1, vector<int>(n2, 0)); 9 10 bool flag = false; 11 for (int i = 0; i < n1; ++i) { 12 if (word1[i] == word2[0]) { 13 min[i][0] = i; 14 flag = true; 15 } else { 16 if (flag) min[i][0] = i; 17 else min[i][0] = i + 1; 18 } 19 } 20 21 flag = false; 22 for (int i = 0; i < n2; ++i) { 23 if (word1[0] == word2[i]) { 24 min[0][i] = i; 25 flag = true; 26 } else { 27 if (flag) min[0][i] = i; 28 else min[0][i] = i + 1; 29 } 30 } 31 32 for (int i = 1; i < n1; ++i) { 33 for (int j = 1; j < n2; ++j) { 34 if (word1[i] == word2[j]) { 35 min[i][j] = min[i - 1][j - 1]; 36 } else { 37 int m = min[i - 1][j] + 1; 38 if (min[i][j - 1] + 1 < m) { 39 m = min[i][j - 1] + 1; 40 } 41 if (min[i - 1][j - 1] + 1 < m) { 42 m = min[i - 1][j - 1] + 1; 43 } 44 min[i][j] = m; 45 } 46 } 47 } 48 49 return min[n1 - 1][n2 - 1]; 50 } 51 52 };
后来看到网上有人把min[i][j]中i和j理解为长度,这样多用了一些空间,不过效率高了一些,不需要在初始化的时候做分别处理。