1.题目描述
2.选题原因
本周学习了动态规划,讲到了编辑距离的算法。恰好看到了leetcode上有这样的题目,因此选择了这道题,就当作巩固知识了!
3.题目分析及算法
3.1分析
动态规划的经典问题,既有思路。
首先考虑两个单词每个字符的匹配情况:
- 1、两个字符相匹配,此时增加的编辑距离+0
- 2、两个字符不匹配,此时增加的编辑距离+1
- 3、上面为空,下面有字符,此时编辑距离+1
- 4、下面为空,上面有字符,此时编辑距离+1
考虑到了所有的情况,那么我们就用一个矩阵来维护所有的情况。
用一个简单的例子,比如说apple
和apology
那么我们就来一起演示一下他的过程:
首先,我们要用一个矩阵来记录最短编辑距离:
a | p | p | l | e | ||
---|---|---|---|---|---|---|
0 | ||||||
a | ||||||
p | ||||||
o | ||||||
l | ||||||
o | ||||||
g | ||||||
y |
怎么读这个表格呢?很简单,比如说
(a, a)
下,就是说从a
编辑到a
;而(l, g)
则是从appl
编辑到apolog
,显而易见,最上面的一行代表着apple
匹配一个空字符串,而最左边一列代表apology
匹配一个空字符串,我们为他初始化
a | p | p | l | e | ||
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | |
a | 1 | |||||
p | 2 | |||||
o | 3 | |||||
l | 4 | |||||
o | 5 | |||||
g | 6 | |||||
y | 7 |
接下来,再让我们来看一下其他的空应当怎么填。
考虑刚才的四种情况,很容易知道我们如果想取得最短的编辑距离,那么就需要判断是要将当前的两个字符对齐还是用一个空格代替其中的一个字符。就很容易转化为下列问题:
如果我们要求(x, y)
点的值,只需要考虑(x - 1, y)
(x, y - 1)
(x - 1, y - 1)
。分别对应:将上面的字符用空格代替,将下面的字符用空格代替,将两个字符对齐。很容易发现,将两个字符对齐对应两种情况:1和2。那么什么时候该+1就取决于两个字符是否相等。
得到式子:
ED(x, y) = min(ED(x, y - 1) + 1, ED(x - 1, y) - 1, ED(x - 1, y - 1) + a(x) == b(y) ? 0 : 1)
填满表格:
a | p | p | l | e | ||
---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | |
a | 1 | 0 | 1 | 2 | 3 | 4 |
p | 2 | 1 | 0 | 1 | 2 | 3 |
o | 3 | 2 | 1 | 1 | 2 | 3 |
l | 4 | 3 | 2 | 2 | 1 | 2 |
o | 5 | 4 | 3 | 3 | 2 | 2 |
g | 6 | 5 | 4 | 4 | 3 | 3 |
y | 7 | 6 | 5 | 5 | 4 | 4 |
得到了最后的结果:
4
3.2算法
构建矩阵并初始化
ED(0, i) = i; ED(j, 0) = j
遍历计算所有节点ED(x, y) = min(ED(x, y - 1) + 1, ED(x - 1, y) - 1, ED(x - 1, y - 1) + a(x) == b(y) ? 0 : 1)
返回ED(x, y)
4.运行结果
5.源代码
class Solution {
public:
int minDistance(string word1, string word2) {
int row = word1.size() + 1;
int col = word2.size() + 1;
int matrix[row][col] = {{0}};
int result = INT_MAX;
if (row == 1) {
return col - 1;
}
if (col == 1) {
return row - 1;
}
//使用0初始化所有的行和列,得到完全不匹配的结果
for (int i = 0; i < row; i++) {
matrix[i][0] = i;
}
for (int i = 0; i < col; ++i) {
matrix[0][i] = i;
}
//构造编辑距离图
for (int i = 1; i < row; i++) {
for (int j = 1; j < col; j++) {
matrix[i][j] = min(matrix[i - 1][j] + 1, min(matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + (word1.at(i - 1) == word2.at(j - 1) ? 0 : 1)));
}
}
return matrix[row - 1][col - 1];
}
};