MENU

LeetCode72. Edit Distance(动态规划)

2019 年 04 月 21 日 • 阅读: 1092 • LeetCode阅读设置

LeetCode72. Edit Distance(动态规划)

  • Hard
  • Accepted:167,332
  • Submissions:450,132

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:

  1. Insert a character
  2. Delete a character
  3. 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')

链接

https://leetcode.com/problems/edit-distance

题意

给定两个单词word1和word2,求把word1变成word2所需要的最少操作次数。支持的操作有三种:删除一个字母,添加一个字母,修改一个字母。

题解

怎么把一个单词变成另一个单词,无非是处理那些不相同的字母,但是怎么保证最少操作次数呢?

假设f(word1, word2)表示word1变成word2的需要的最少操作次数,那么:

  f("abbc", "acc")
= f("abb", "ac")  // c = c
= 1 + min(f("ab", "ac")  // delete b
=         f("abb", "c")  // insert c
=         f("ab",  "a")) // modify b->c

如果我们使用dp[i][j]表示word1[0, i-1]变成word2[0, j-1]的最少操作次数,那么:

$dp[i][j]=\left\{\begin{array}{cc}{dp[i-1][j-1]} & {word1[i-1] = word2[j-1]} \\ {\min (dp[i-1][j-1],dp[i][j-1],dp[i-1][j]) + 1} & {word1[i-1] \neq word2[j-1]} \end{array}\right.$

dp[i-1][j-1]对应着修改操作,dp[i][j-1]对应着插入操作,dp[i-1][j]对应着删除操作。

当然,当i为0时,dp[0][j]=j,当j为0时,dp[i][0]=i。

至此,我们可以用自顶向下的递归或者自底向上的动态规划来解决这个问题。

时间复杂度$O(nm)$,空间复杂度$O(nm)$,显然,空间复杂度可以进行优化为O(n),可以参考LeetCode64. Minimum Path Sum(动态规划)

代码

  • Runtime: 16 ms, faster than 77.35% of C++ online submissions for Edit Distance.
  • Memory Usage: 11.3 MB, less than 23.70% of C++ online submissions for Edit Distance.
class Solution {
public:
    int minDistance(string word1, string word2) {
        int n = word1.length(), m = word2.length();
        vector <vector<int> > dp(n + 1, vector<int>(m + 1, 0));
        for (int j = 0; j <= m; ++j)
            dp[0][j] = j;
        for (int i = 0; i <= n; ++i)
            dp[i][0] = i;
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 1; j <= m; ++j)
            {
                if (word1[i - 1] == word2[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;
            }
        }
        return dp[n][m];
    }
};

参考


The end.
2019年4月21日 星期日
最后编辑于: 2019 年 05 月 21 日