代码
/**
* @param str1 string字符串
* @param str2 string字符串
* @return int整型
*/
function editDistance(str1, str2) {
// write code here
const m = str1.length,
n = str2.length;
// dp[i][j] 表示,str2 的首字母到 i ,str1 的首字母到 j 的编辑距离
const dp = new Array(n + 1).fill(1).map(() => new Array(m + 1).fill(0));
// 行初始化,str1 首字母为空字符串时,编辑距离为上一次的编辑距离 + 1
// 也就是上一个 str2 字符所在下标 i - 1 的编辑距离 + 1
for (let i = 1; i <= n; i++) {
dp[i][0] = dp[i - 1][0]; // 也可以直接写 i,为了理解清 dp[i][j] 的含义这里采用 dp[i - 1][0]
}
// 列的初始化类似行初始化,str2 的首字母为空字符串时,相对于 str1 当前位置 j 的编辑距离
for (let j = 1; j <= m; j++) {
dp[0][j] = dp[0][j - 1]; // j
}
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (str2[i - 1] === str1[j - 1])
// 不需要编辑,直接选取回退当前两个字符的情况
// 两个字符相同,这多出来的字符就不用操作,操作次数与两个子串的前一个相同
// 因此有dp[i][j]=dp[i−1][j−1]dp[i][j] = dp[i - 1][j - 1]dp[i][j]=dp[i−1][j−1]
dp[i][j] = dp[i - 1][j - 1];
else {
// 需要编辑,从前面中选取最小的加以编辑
// 递推公式应该由状态转移到的情况得出:
// 两个字符不相同,那么这两个字符需要编辑
// 但是此时的最短的距离不一定是由修改子串得出,也有可能是删除某个字符或者增加某个字符
// 因此我们选取这三种情况的最小值增加一个编辑距离
// 即,dp[i][j]=min(dp[i−1][j−1],min(dp[i−1][j],dp[i][j−1]))+1
dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
}
}
}
// 拿到下标为 m , n 的编辑距离,总的编辑距离有前面各个子编辑距离得出
return dp[n][m];
}