LeetCode题练习与总结:编辑距离--72

178 篇文章 0 订阅
113 篇文章 0 订阅

一、题目描述

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

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

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

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

提示:

  • 0 <= word1.length, word2.length <= 500
  • word1word2 由小写英文字母组成

二、解题思路

定义一个二维数组 dp,其中 dp[i][j] 表示将 word1 的前 i 个字符转换为 word2 的前 j 个字符所需要的最少操作数。对于 dp 数组的每一个元素,我们可以根据以下情况来更新它的值:

1. 如果 word1[i] == word2[j],则 dp[i][j] = dp[i-1][j-1],因为当前字符匹配,所以不需要任何操作,直接继承前面的结果。

2. 如果 word1[i] != word2[j],则 dp[i][j] 可以通过以下三种操作之一得到:

  • 插入一个字符:dp[i][j] = dp[i][j-1] + 1,相当于将 word2[j] 插入到 word1 中。
  • 删除一个字符:dp[i][j] = dp[i-1][j] + 1,相当于将 word1[i] 删除。
  • 替换一个字符:dp[i][j] = dp[i-1][j-1] + 1,相当于将 word1[i] 替换为 word2[j]
  • 在这三种操作中,我们选择操作数最少的一种。

初始化 dp 数组时,dp[0][j] 表示将一个空字符串转换为 word2 的前 j 个字符所需要的操作数,显然为 j;同理,dp[i][0] 表示将 word1 的前 i 个字符转换为空字符串所需要的操作数,显然为 i

三、具体代码

class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();
        
        // dp[i][j] 表示将 word1 的前 i 个字符转换为 word2 的前 j 个字符所需要的最少操作数
        int[][] dp = new int[m + 1][n + 1];
        
        // 初始化 dp 数组
        for (int i = 0; i <= m; i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = j;
        }
        
        // 动态规划过程
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
                }
            }
        }
        
        // 返回最终结果
        return dp[m][n];
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 我们有一个双层循环,分别遍历字符串 word1 和 word2 的所有字符。
  • 外层循环遍历 word1 的每个字符,共有 m 次迭代(其中 m 是 word1 的长度)。
  • 内层循环遍历 word2 的每个字符,共有 n 次迭代(其中 n 是 word2 的长度)。
  • 在循环的每次迭代中,我们执行的是常数时间的操作,即比较字符、更新动态规划数组。
  • 因此,总的时间复杂度是 O(m * n),即两个字符串长度的乘积。
2. 空间复杂度
  • 我们定义了一个二维数组 dp,其大小为 (m + 1) * (n + 1),其中 m 和 n 分别是字符串 word1 和 word2 的长度。
  • 这个二维数组用于存储从 word1 的前 i 个字符转换到 word2 的前 j 个字符所需的最少操作数。
  • 因此,空间复杂度也是 O(m * n),即两个字符串长度的乘积。

五、总结知识点

1. 动态规划(Dynamic Programming, DP):

  • 动态规划是一种算法设计技术,用于求解具有重叠子问题和最优子结构特性的复杂问题。
  • 它将问题分解为较小的子问题,并存储这些子问题的解,以避免重复计算。
  • 在本问题中,dp[i][j] 表示将 word1 的前 i 个字符转换为 word2 的前 j 个字符所需要的最少操作数。

2. 二维数组:

  • 二维数组是一种数据结构,用于存储多个相同类型的元素,这些元素以行和列的形式排列。
  • 在本问题中,dp 是一个二维数组,用于存储不同子问题的解。

3. 字符串操作:

  • charAt(int index) 方法用于获取字符串中指定索引处的字符。
  • 在本问题中,使用 charAt(i - 1) 来获取 word1 和 word2 字符串中的字符,因为数组的索引从 0 开始,而 dp 数组的维度是从 1 开始的。

4. 数学函数:

  • Math.min() 函数用于在多个值中选择最小值。
  • 在本问题中,使用 Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) 来确定在当前字符不匹配时,进行插入、删除或替换操作中的最小操作数。

5. 循环结构:

  • 使用了双层循环来遍历 word1 和 word2 的所有字符组合,以填充 dp 数组。

6. 边界条件处理:

  • 使用了单独的循环来初始化 dp 数组的边界条件,即当其中一个字符串为空时,转换为另一个字符串所需的操作数。

7. 递推关系:

  • 通过比较当前字符是否相等,定义了 dp 数组的递推关系,即如果字符相等,则操作数不变;如果字符不等,则取插入、删除、替换三种操作中的最小操作数加一。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直学习永不止步

谢谢您的鼓励,我会再接再厉的!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值