72. Edit Distance

问题

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

例子

abc bad
3

分析

最优化问题 + 大问题可以用小问题来解决 => 动态规划

  1. 状态表
    dp[i][j] word1[0, i-1]转化为word2[0, j-1]的最小步数

  2. 初始状态
    dp[0][0] = 0 空串=空串,不需要转化;
    dp[i][0] = i, i >= 1 长度为i的字符串转化为空串,需要添加i个字符串;
    dp[0][j] = j, j >= 1 空串转化为长度为j的字符串,需要删除i个字符串。

  3. 状态转移方程
    dp[i][j] = dp[i - 1][j - 1], if word1[i - 1] == word2[j - 1]
    注:当word1的第i个字符和word2的第j个字符相等时, word1[0, i-1]转化为word2[0, j-1]的最小步数等于word1[0, i-2]转化为word2[0, j-2]的最小步数
    dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1, if word1[i - 1] != word2[j - 1]
    注:当word1的第i个字符和word2的第j个字符不相等时,word1可以先转换、删除第i个字符,或者在word2添加第j个字符,然后再进一步转化为word2。第一步都需要1次转化,第二步分别需要dp[i - 1][j - 1]、dp[i - 1][j]和dp[i][j - 1]次转化。取最小值即可。

要点

dp

时间复杂度

O(mn)

空间复杂度

O(mn)

代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size(), n = word2.size();
        vector> dp(m + 1, vector(n + 1, 0));
        for (int i = 1; i <= m; i++)
            dp[i][0] = i;
        for (int j = 1; j <= n; j++)
            dp[0][j] = j;

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; 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[m][n];
    }
};

空间复杂度为O(2n)的代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size(), n = word2.size();
        vector> dp(2, vector(n + 1, 0));
        for (int j = 1; j <= n; j++)
            dp[0][j] = j;

        int flag = 0;
        for (int i = 1; i <= m; i++) {
            dp[!flag][0] = i;
            for (int j = 1; j <= n; j++) {
                if (word1[i - 1] == word2[j - 1]) dp[!flag][j] = dp[flag][j - 1];
                else dp[!flag][j] = min(dp[flag][j - 1], min(dp[flag][j], dp[!flag][j - 1])) + 1;
            }
            flag = !flag;
        }
        return dp[flag][n];
    }
};

空间复杂度为O(n)的代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size(), n = word2.size();
        vector dp(n + 1, 0);
        for (int j = 1; j <= n; j++)
            dp[j] = j;
            
        for (int i = 1; i <= m; i++) {
            int pre = dp[0];
            dp[0] = i;
            for (int j = 1; j <= n; j++) {
                int temp = dp[j];
                if (word1[i - 1] == word2[j - 1]) dp[j] = pre;
                else dp[j] = min(pre, min(dp[j], dp[j - 1])) + 1;
                pre = temp;
            }
        }
        return dp[n];
    }
};

你可能感兴趣的:(72. Edit Distance)