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

一、题目描述

给你两个单词 word1word2请返回将 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

三、具体代码

java 复制代码
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 数组的递推关系,即如果字符相等,则操作数不变;如果字符不等,则取插入、删除、替换三种操作中的最小操作数加一。

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

相关推荐
Mr. zhihao41 分钟前
深入解析redis基本数据结构
数据结构·数据库·redis
辰海Coding1 小时前
MiniSpring框架学习-完成的 IoC 容器
java·spring boot·学习·架构
念何架构之路1 小时前
Go语言加密算法
数据结构·算法·哈希算法
AI科技星1 小时前
《数学公理体系·第三部·数术几何》(2026 年版)
c语言·开发语言·线性代数·算法·矩阵·量子计算·agi
小小编程路1 小时前
C++ 多线程与并发
java·jvm·c++
失去的青春---夕阳下的奔跑1 小时前
560. 和为 K 的子数组
数据结构·算法·leetcode
AI视觉网奇1 小时前
linux 检索库 判断库是否支持
java·linux·服务器
黎阳之光2 小时前
黎阳之光:以视频孪生重构智慧医院信息化,打造高标项目核心竞争力
大数据·人工智能·物联网·算法·数字孪生
她的男孩2 小时前
从零搭一个企业后台,为什么我把能力拆成 Starter 和 Plugin
java·后端·架构
RainCity2 小时前
Java Swing 自定义组件库分享(七)
java·笔记·后端