问题描述:
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
这道题的大致意思就是给你两个字符串Word1和Word2,要你使用最少的操作次数,将Word1转换为Word2,其中的操作只允许插入字符、删除字符以及替换字符,每使用其中的一种就算是一次操作。
其实我刚开始做的时候根本没想到这是一道动态规划的题,一脸懵逼,最后还是看了大神博客的解析才明白的。
Word1要转换为Word2,实际上可以转换为Word1的子字符串转为Word2的子字符串的操作次数再加上最后一位的变换,如果最后一位相等,就不需要变换,直接就是Word1的子字符串转为Word2的子字符串,这就要取决于Word1的子字符串转为Word2子字符串的最小操作次数是多少了。他实际上有三种情况,即代码中的那三种情况;子字符串长度一直减小,最后减到1,就是最初始的操作了。所以我们倒过来,从长度为1开始,往后推,就可以知道答案了。这就是动态规划的核心。
具体解析可以看这位大神的解析,我也是看了才明白的:
beiyetengqing的编辑距离 (edit distance)
我的文字表述的不是太清楚,大家可以伴着代码和注释来看,好理解一点,因为代码就是典型的动态规划式代码,一个二维数组,然后从左上角不断往右下角推值:
public int minDistance(String word1, String word2) {
//如果两者有一个字符串长度为0,那么操作次数一定是另一个字符串的长度
if(word1.length() == 0)
return word2.length();
if(word2.length() == 0)
return word1.length();
//distance[i][j]即当Word1长度为i,Word2长度为j时转换需要的操作次数
//这道题实际上是一道动态规划的题
int [][]distance = new int[word1.length()+1][word2.length()+1];
//先对数组的边进行初始化
//当Word2长度为0时,distance[i][0]=i,即等于Word1的长度
for(int i = 0; i <= word1.length(); i++)
distance[i][0] = i;
//当Word1长度为0时,distance[0][j]=j,即等于Word2的长度
for(int j = 0; j <= word2.length(); j++)
distance[0][j] = j;
//然后就根据前面子字符串已知道的操作次数来推导后面未知的操作次数
for(int i = 1; i <= word1.length(); i++) {
for(int j = 1; j <= word2.length(); j++) {
//即如果当前Word1第i个字符和Word2第j个字符相等的话,Word1转为Word2的操作次数,应该等于distance[i-1][j-1]
if(word1.charAt(i-1) == word2.charAt(j-1)) {
distance[i][j] = distance[i-1][j-1];
}
//否则,就是另外三种可能的情况,取最小的操作次数,再加上对这一位数的操作,即1,就是distance[i][j]的值
else {
distance[i][j] = Math.min(distance[i-1][j], Math.min(distance[i][j-1], distance[i-1][j-1])) + 1;
}
}
}
//最后直接返回从二维数组左上角开始往右下角推导的结果
return distance[word1.length()][word2.length()];
}
谢谢大家观看我的博客。如果大家有不明白的地方,或者文中有出错的地方,欢迎大家指出,谢谢!