1652755505(1).png

思路

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]
递推公式:
if (word1[i - 1] == word2[j - 1]) 不操作
if (word1[i - 1] != word2[j - 1]) 增 删 换
——————————————————————————————————————————————————————-
if (word1[i - 1] != word2[j - 1]),此时就需要编辑了,如何编辑呢?

  • 操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。

即 dp[i][j] = dp[i - 1][j] + 1;

  • 操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。

即 dp[i][j] = dp[i][j - 1] + 1;
这里有同学发现了,怎么都是删除元素,添加元素去哪了。
word2添加一个元素,相当于word1删除一个元素,例如 word1 = “ad” ,word2 = “a”,word1删除元素’d’ 和 word2添加一个元素’d’,变成word1=”a”, word2=”ad”, 最终的操作数是一样!【它们是等价的,即你可以把所有的删除操作 转换成 增加操作】

  • 操作三:替换元素,word1替换word1[i - 1],使其与word2[j - 1]相同,此时不用增加元素,那么以下标i-2为结尾的word1 与 j-2为结尾的word2的最近编辑距离 加上一个替换元素的操作。

综上,当 if (word1[i - 1] != word2[j - 1]) 时取最小的,即:dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;

  1. var minDistance = function(word1, word2) {
  2. // 思路太绝了,我只会模仿
  3. // dp[i][j]:以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
  4. // 编辑操作:增、删、改
  5. // 核心难点:增加操作和删除操作其实本质是相同的
  6. let len1 =word1.length
  7. let len2 =word2.length
  8. let dp =new Array(len1+1).fill().map(()=>new Array(len2+1).fill(0))
  9. // 一方为空字符串时,编辑操作就是删除,所以初始化为i
  10. for(let i=0;i<=len1;i++){
  11. dp[i][0] =i
  12. }
  13. for(let j=0;j<=len2;j++){
  14. dp[0][j] =j
  15. }
  16. for(let i=1;i<=len1;i++){
  17. for(let j=1;j<=len2;j++){
  18. if(word1[i-1]===word2[j-1]){
  19. // 相等时 不操作
  20. dp[i][j] =dp[i-1][j-1]
  21. }else{
  22. // 增/删,改
  23. dp[i][j] =Math.min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) +1
  24. }
  25. }
  26. }
  27. return dp[len1][len2]
  28. };