LeetCode 72. Edit Distance 编辑距离 (C++/Java)
题目:
Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.
You have the following 3 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')
分析:
给定两个单词,求word1转换到word2需要的最少步骤,转换的操作有三种,分别是插入一个字符,删除一个字符,替换一个字符。
d(word1, word2)用来求两个单词转换的需要的最小步数,那么如果当两个单词的最后一个字符是相同的,则d(word1, word2) = d(word1', word2')其word1'和word2'是分别去掉最后一个字符的单词。
如果最后两个字符不相同时,我们就需要操作来进行转换,一种是在word1后增加一个字符,是其最后一个字符和word2的最后一个字符相同,一种是删去word1的最后一个字符,一种是将word1的最后一个字符转换成word2的最后一个字符,那么此时最小的步数就是前三个操作的最小值加上1.
可能有同学会问为什么不在word2上进行操作,实际上操作转换这一步是有5个子问题的,但实际上在word1后增加一个字符和word2最后字符相同,相当于在word2后删除字符;删去word1的字符相当于在word2后增加一个字符和word1最后字符相同;而转换操作明显是一样的,所以就合并成为了三个子问题。
当递归执行到其中一个串为空串时,则加上另一个串的长度即可,相当于删去所有的字符。
程序:
C++
class Solution { public: int minDistance(string word1, string word2) { int l1 = word1.length(); int l2 = word2.length(); dp = vector<vector<int>>(l1+1, vector<int>(l2+1, -1)); return minDistance(word1, word2, l1, l2); } private: vector<vector<int>> dp; int minDistance(string& word1, string& word2, int l1, int l2){ if(l1 == 0) return l2; if(l2 == 0) return l1; if(dp[l1][l2] >= 0) return dp[l1][l2]; int res = 0; if(word1[l1-1] == word2[l2-1]){ res = minDistance(word1, word2, l1-1, l2-1); dp[l1][l2] = res; return res; } res = min(minDistance(word1, word2, l1-1, l2), min(minDistance(word1, word2, l1, l2-1), minDistance(word1, word2, l1-1, l2-1))) + 1; dp[l1][l2] = res; return res; } };
Java
class Solution { public int minDistance(String word1, String word2) { int l1 = word1.length(); int l2 = word2.length(); dp = new int[l1+1][l2+1]; for(int i = 0; i < dp.length; ++i){ for(int j = 0; j < dp[i].length; ++j){ dp[i][j] = -1; } } return minDistance(word1, word2, l1, l2); } private int minDistance(String word1, String word2, int l1, int l2){ if(l1 == 0) return l2; if(l2 == 0) return l1; if(dp[l1][l2] >= 0) return dp[l1][l2]; int res = 0; if(word1.charAt(l1-1) == word2.charAt(l2-1)){ res = minDistance(word1, word2, l1-1, l2-1); }else{ res = Math.min(minDistance(word1, word2, l1-1, l2), Math.min(minDistance(word1, word2, l1, l2-1), minDistance(word1, word2, l1-1, l2-1))) + 1; } dp[l1][l2] = res; return res; } private int[][] dp; }