LeetCode 72:编辑距离(Edit Distance)------ 题解 ✅
🔗 题目链接
👉 https://leetcode.cn/problems/edit-distance/
📖 内容概要
给定两个字符串 word1 和 word2,你可以对 word1 执行以下三种操作之一:
- 插入一个字符
- 删除一个字符
- 替换一个字符
返回将 word1 转换成 word2 所需的 最少操作次数。
✅ 经典二维 DP
✅ 面试 Hard 必考题
✅ 字符串 DP 的巅峰之作
💡 解题思路(核心)
一、DP 状态定义(必须背)
java
dp[i][j] =
将 word1 的前 i 个字符
转换成 word2 的前 j 个字符
所需的最少操作次数
二、初始化(边界条件)
| 情况 | 含义 | 值 |
|---|---|---|
dp[i][0] |
删光 word1 |
i |
dp[0][j] |
插入 word2 |
j |
java
for (int i = 0; i <= len1; i++) dp[i][0] = i;
for (int j = 0; j <= len2; j++) dp[0][j] = j;
🔁 状态转移(灵魂)
✅ 情况 1:当前字符相同
java
if (w1[i-1] == w2[j-1]) {
dp[i][j] = dp[i-1][j-1];
}
- 不需要任何操作
- 直接继承之前的状态
❌ 情况 2:当前字符不同
三种操作取最小值:
| 操作 | 状态来源 | 含义 |
|---|---|---|
| 替换 | dp[i-1][j-1] + 1 |
改字符 |
| 删除 | dp[i-1][j] + 1 |
删 word1[i] |
| 插入 | dp[i][j-1] + 1 |
插 word2[j] |
实际上,删除和插入是相对的,插 word2[j]和删word2[j]是等价的
java
dp[i][j] = Math.min(
Math.min(
dp[i-1][j] + 1, // 删除
dp[i][j-1] + 1 // 插入
),
dp[i-1][j-1] + 1 // 替换
);
✅ AC 代码(Java,完全基于你的代码)
java
class Solution {
public int minDistance(String word1, String word2) {
char[] w1 = word1.toCharArray();
char[] w2 = word2.toCharArray();
int len1 = word1.length();
int len2 = word2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
// 初始化
for (int i = 0; i <= len1; i++) dp[i][0] = i;
for (int j = 0; j <= len2; j++) dp[0][j] = j;
// 状态转移
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (w1[i - 1] == w2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(
Math.min(
dp[i - 1][j] + 1, // 删除
dp[i][j - 1] + 1 // 插入
),
dp[i - 1][j - 1] + 1 // 替换
);
}
}
}
return dp[len1][len2];
}
}
⏱️ 复杂度分析
| 指标 | 复杂度 |
|---|---|
| 时间复杂度 | O(n × m) |
| 空间复杂度 | O(n × m) |
✅ 一句话总结
编辑距离 = 用 DP 枚举"增 / 删 / 替"三种操作的最小代价。
📌 面试加分点(建议背)
- ✅ 为什么初始化是
dp[i][0] = i - ✅ 为什么替换是
dp[i-1][j-1] + 1 - ✅ 插入和删除为什么对称
- ✅ 如何用滚动数组优化到 O(min(n, m))