[LeetCode] 72. Edit Distance
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 -> ine ntion (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
andword2
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 的前 j - 1 个字符的子问题
我在讨论区看到一个很好的评论帮助理解,贴在这里。
- 对“dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作。”的补充理解:
- 以 word1 为 "horse",word2 为 "ros",且 dp[5][3] 为例,即要将 word1的前 5 个字符转换为 word2的前 3 个字符,也就是将 horse 转换为 ros,因此有:
- (1) dp[i-1][j-1],即先将 word1 的前 4 个字符 hors 转换为 word2 的前 2 个字符 ro,然后将第五个字符 word1[4](因为下标基数以 0 开始) 由 e 替换为 s(即替换为 word2 的第三个字符,word2[2])
- (2) dp[i][j-1],即先将 word1 的前 5 个字符 horse 转换为 word2 的前 2 个字符 ro,然后在末尾补充一个 s,即插入操作
- (3) dp[i-1][j],即先将 word1 的前 4 个字符 hors 转换为 word2 的前 3 个字符 ros,然后删除 word1 的第 5 个字符
时间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 };
相关题目