Edit Distance 算法实现及其设计原理

题目:

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:

  1. Insert a character
  2. Delete a character
  3. 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);
	}

 

点赞