【力扣刷题练习】72. 编辑距离

题目描述:

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符

题目解答:

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, 0));

        for (int i = 0; i <= m; ++i) {
            for (int j = 0; j <= n; ++j) {
                if (i == 0 || j == 0)
                    i == 0 ? dp[i % 2][j] = j : dp[i % 2][j] = i;
                else {
                    dp[i % 2][j] =
                        min(dp[(i - 1) % 2][j - 1],
                            min(dp[(i - 1) % 2][j], dp[i % 2][j - 1])) +
                        1;
                    if (word1[i - 1] == word2[j - 1])
                        dp[i % 2][j] =
                            min(dp[i % 2][j], dp[(i - 1) % 2][j - 1]);
                }
            }
        }

        return dp[m % 2][n];
    }
};

题目思路:

为计算两个字符串之间的编辑距离(Levenshtein距离),使用动态规划的思想。

  1. 初始化数组:

    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    

    初始化一个大小为(m+1) × (n+1)的二维数组dp,其中dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最小编辑距离。

  2. 填充数组:

    for (int i = 0; i <= m; ++i) {
        for (int j = 0; j <= n; ++j) {
    

    双重循环遍历word1word2的所有可能的前缀子串。

  3. 处理第一行和第一列:

    if (i == 0 || j == 0)
        i == 0 ? dp[i % 2][j] = j : dp[i % 2][j] = i;
    

    当其中一个字符串为空时,编辑距离就是另一个字符串的长度。这里使用了条件表达式,如果i为0,那么dp[i % 2][j]就被赋值为j,否则被赋值为i

  4. 处理其他情况:

    else {
        dp[i % 2][j] = min(dp[(i - 1) % 2][j - 1], min(dp[(i - 1) % 2][j], dp[i % 2][j - 1])) + 1;
        if (word1[i - 1] == word2[j - 1])
            dp[i % 2][j] = min(dp[i % 2][j], dp[(i - 1) % 2][j - 1]);
    }
    

    对于非第一行和第一列的位置,计算编辑距离并填充dp数组。如果当前字符相同,则直接继承前一步的编辑距离,否则在前一步的基础上进行插入、删除或替换操作,选择最小的编辑距离。

  5. 最终结果:

    return dp[m % 2][n];
    

    返回dp[m % 2][n],表示将word1的前m个字符转换为word2的前n个字符所需的最小编辑距离。

这段代码的时间复杂度为O(m * n),空间复杂度为O(min(m, n)),因为滚动数组优化仅保留了两行的状态。

你可能感兴趣的:(力扣刷题练习,leetcode,算法,职场和发展)