首页 > 技术文章 > [LeetCode] 72. Edit Distance

cnoodle 2020-04-07 00:49 原文

Given two strings word1 and word2, return the minimum number of operations required to convert word1 to word2.

You have the following three operations permitted on a word:

  • Insert a character
  • Delete a character
  • 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') 

Constraints:

  • 0 <= word1.length, word2.length <= 500
  • word1 and word2 consist of lowercase English letters.

编辑距离。

题意是给两个字符串word1和word2,请返回将 word1 转换成 word2 所使用的最少操作数。这是动态规划的经典题。创建一个二维的数组 dp[i][j] ,代表 word1 到 i 位置转换成 word2 到 j 位置需要最少步数。要让两个单词相同,分三种情况,

  • word1减去一个字母 === word2加上一个字母(这两者是等价的所以是同一种情况)
  • word1加上一个字母 === word2减去一个字母(等价)
  • word1修改一个字母 === word2修改一个字母(等价)

所以判断DP下一步的值的时候需要判断当前字母是否相同,若相同则不需要做任何转换,DP值来源于上一个位置的DP值,dp[i][j] = dp[i - 1][j - 1];若不相同则需要判断如下三种情况哪一种的开销小,

  • dp[i - 1][j] - A的前i - 1个字符和B的前j个字符的子问题
  • dp[i][j - 1] - A的前i个字符和B的前j - 1个字符的子问题
  • dp[i-1][j-1] - A的前 i - 1个字符和B的前i  - 1个字符的子问题

时间O(mn)

空间O(mn)

Java实现

 1 class Solution {
 2     public int minDistance(String word1, String word2) {
 3         int len1 = word1.length();
 4         int len2 = word2.length();
 5         int[][] dp = new int[len1 + 1][len2 + 1];
 6         for (int i = 0; i <= len1; i++) {
 7             dp[i][0] = i;
 8         }
 9         for (int j = 0; j <= len2; j++) {
10             dp[0][j] = j;
11         }
12         for (int i = 1; i <= len1; i++) {
13             for (int j = 1; j <= len2; j++) {
14                 if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
15                     dp[i][j] = dp[i - 1][j - 1];
16                 } else {
17                     dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
18                 }
19             }
20         }
21         return dp[len1][len2];
22     }
23 }

 

JavaScript实现

 1 /**
 2  * @param {string} word1
 3  * @param {string} word2
 4  * @return {number}
 5  */
 6 var minDistance = function(word1, word2) {
 7     let len1 = word1.length;
 8     let len2 = word2.length;
 9     let dp = Array(word1.length + 1)
10         .fill(null)
11         .map(() => Array(word2.length + 1).fill(0));
12     for (let i = 0; i <= len1; i++) {
13         dp[i][0] = i;
14     }
15     for (let j = 0; j <= len2; j++) {
16         dp[0][j] = j;
17     }
18     for (let i = 1; i <= len1; i++) {
19         for (let j = 1; j <= len2; j++) {
20             if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
21                 dp[i][j] = dp[i - 1][j - 1];
22             } else {
23                 dp[i][j] =
24                     1 +
25                     Math.min(
26                         Math.min(dp[i - 1][j], dp[i][j - 1]),
27                         dp[i - 1][j - 1]
28                     );
29             }
30         }
31     }
32     return dp[i][j];
33 };

 

相关题目

72. Edit Distance

583. Delete Operation for Two Strings

LeetCode 题目总结

推荐阅读