0
点赞
收藏
分享

微信扫一扫

leetcode:72. 编辑距离

素锦时年_1b00 2022-04-24 阅读 78
leetcode

题目来源

  • leetcode

题目描述

在这里插入图片描述

题目解析

递归

共有三种变换方式,插入一个字符,删除一个字符,和替换一个字符

分析:

  • 不可以用map统计字符出现的频率,因为字符串的顺序很重要
  • [删除] 和[添加]是等价的。比如"qwe"与"qwer",删除"qwer"的r与给"qwe"添加一个r是等价的。所以在比较的时候,需要尝试三种操作,因为谁也不知道当前的操作会对后面产生什么样的营销。

对于当前比较的两个字符word1[i]word2[j]

  • 如果两者相同,直接跳到下一个为止
  • 如果两者不相同,有三种处理方法:
    • 第一种:(在word1[i])插入一个word2[j],那么word2[j]的字符就跳过了,接着比较word1[i]word2[j + 1]即可
    • 第二种:将word1[i]字符直接删掉,接着比较word1[i+1] word2[j]即可
    • 第三者:将word[i]修改为word2[j],接着比较 word1[i+1] word[j+1]

问题是,这种操作的时间是指数级别的,我们加个缓存优化一下,就可以把时间给降下来了。
代码如下:

class Solution {
public:
    int minDistance(string word1, string word2){
        int m = word1.size(), n = word2.size();
        std::vector<std::vector<int>> cache(m, std::vector<int>(n));
        return helper(word1, 0, word2, 0, cache);
    }

private:
    int helper(std::string &word1, int i, std::string &word2, int j,}
};

在这里插入图片描述

动态规划

(1)定义状态

  • f[i][j]表示将word1的前i个字符变成word2的前j个字符所需要进行的最少操作次数
  • 需要考虑 word1 或 word2 一个字母都没有,即全增加/删除的情况,所以预留dp[0][j] dp[i][0]

(2)状态转移方程:对于f[i][j],考虑word1的第i个字符与word2的第j个字符,分为两种情况:

  • word1[i] == word2[j],则f[i][j] == f[i - 1][j - 1]
  • word1[i] != word2[j],我们有三种选择,替换、删除、插入:
    • 替换: 替换word1的第i个字符或者替换word2的第j个字符,则f[i][j] == f[i - 1][j - 1] + 1
    • 删除: 删除word1的第i个字符或者删除word2的第j个字符,则f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
    • 插入: 在 word2[j] 后面添加 word1[i]或者在word1[i]后添加word2[j],则f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(3)计算顺序:

  • 按顺序计算,当计算 dp[i][j] 时,dp[i - 1][j] dp[i][j - 1]dp[i - 1][j - 1]均已经确定了

(4)dp如何初始化:从一个字符串变成空字符串,非空字符串的长度就是编辑距离

for (int i = 0; i <= len1; i++) {
    dp[i][0] = i;
}

for (int j = 0; j <= len2; j++) {
    dp[0][j] = j;
}

在这里插入图片描述
(5)考虑输出

  • 输出:dp[len1][len2] 符合语义,即 word1[0…len) 转换成 word2[0…len2) 的最小操作数

(6)空间优化:

  • 根据状态转移方程,当前要填写的单元格的数值,完全取决于它的左边一格、上边一格,左上边主对角线上一个的数值。如下图:

在这里插入图片描述

  • 因此,有两种经典的空间优化方案:① 滚动数组;② 把主对角线上要参考的数值使用一个新变量记录下来,然后在一维表格上循环赋值。由于空间问题不是这道题的瓶颈,可以不做这样的空间优化。
class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size(), n = word2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        for (int i = 0; i <= m; ++i) dp[i][0] = i;
        for (int i = 0; i <= n; ++i) dp[0][i] = i;
        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];
    }
};
  • 怎么填表
  • 关于动画
举报

相关推荐

0 条评论