力扣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[i][j] 表示的是:将 word1 的前 i 个字符,转换为 word2 的前 j 个字符,所需要的编辑距离(即最小操作数)

两种情况:字符相等与字符不相等

情况一:字符相等

word1 的第 i 个字符 word1[i - 1] 等于 word2 的第 j 个字符 word2[j - 1],那么不需要做任何编辑操作,此时 dp[i][j] = dp[i - 1][j - 1]

情况二:字符不等

考虑三种编辑操作:

替换

word1[i - 1] 替换为 word2[j - 1],此时最后一个字符相同,操作数加一,即 dp[i][j] = dp[i - 1][j - 1] + 1

插入

在 word1 中插入word2[j - 1],由于此时 word1 的长度变为 i + 1,那么相当于将 word1 的前 i 个字符转换为 word2 的前 j - 1 个字符后,再插入一个字符,即dp[i][j] = dp[i][j - 1] + 1

删除

从 word1 中删除 word1[i - 1],由于此时 word1 的长度变为 i - 1,那么相当于将 word1 的前 i - 1个字符转换为 word2 的前 j 个字符,即 dp[i][j] = dp[i - 1][j] + 1

最终,应该取这三种情况的最小值

边界情况

如果有一个串为空串,另一个串不为空串且长度为 k,那么只需要执行 k 次删除操作或增加操作即可

所以 dp[i][0] = i, dp[0][j] = j

java 复制代码
class Solution {
    public int minDistance(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        if(n * m == 0) {
            // 如果有空串,只需执行 n 或 m 次删除或添加操作
            return n + m;
        }

        int[][] dp = new int[n + 1][m + 1];
        for(int i = 0; i < n + 1; i++) {
            dp[i][0] = i;
        }
        for(int j = 0; j < m + 1; j++) {
            dp[0][j] = j;
        }

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

可以将 dp 数组简化为一个两行数组,因为dp[i][j]只和它左上、左边、上方的元素相关

再进一步,也可以只用一个一维数组

java 复制代码
class Solution {
    public int minDistance(String word1, String word2) {
        int m = word2.length();
        char[] w2 = word2.toCharArray();

        int[] dp = new int[m + 1];
        for(int j = 0; j < m; j++) {
            // dp[0] 相当于 dp[i][0], 值为 i , 因此这里不做初始化,遍历 word1 再处理
            dp[j + 1] = j + 1;
        }

        for(char ch : word1.toCharArray()) {
            int pre = dp[0]; // 每次当 j = 0,dp[i][1] 的 左上角就是 dp[i - 1][0]
            dp[0]++; // 每遍历一个 word1[i - 1], dp[i][0]都更新为 i , 这里由于是一维数组,因此值自增就表示值为 i
            for(int j = 0; j < m; j++) {
                int tmp = dp[j + 1];
                if(ch == w2[j]) {
                    dp[j + 1] = pre;
                } else {
                    // pre 表示左上角,dp[j + 1] 表示上方,dp[j] 表示左边
                    dp[j + 1] = Math.min(Math.min(dp[j + 1], dp[j]), pre) + 1;
                }
                pre = tmp;
            }
        }

        return dp[m];
    }
}
相关推荐
叠层归一研究院41 分钟前
基于极限自指的叠层归一宇宙结构理论——无元外部封闭系统的内生区分模型
人工智能·经验分享·算法·agi
Selvaggia2 小时前
Diffusion Model 的基本原理与模型架构
算法
wabs6663 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
hanlin033 小时前
刷题笔记:力扣第41题-缺失的第一个正数
笔记·算法·leetcode
shehuiyuelaiyuehao4 小时前
算法50,分治归并,数组中的逆序对
java·算法
阳明山水4 小时前
校准分位数驱动智能库存决策
人工智能·深度学习·算法·机器学习·架构
别动我齐刘海6 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
zhangfeng11336 小时前
《从“人工适配“到“智能生成“:KernelSwift 跨国产芯片算子迁移全栈方案解读》 —— 强调范式跃迁和跨硬件属性,适合偏架构分析的写法
人工智能·算法·华为·ai编程·npu
0+1116 小时前
算法 --滑动窗口
c++·算法·leetcode
天真小巫6 小时前
2026.9.19总结
职场和发展