LeetCode 583:两个字符串的删除操作(Delete Operation for Two Strings)------ 题解 ✅
🔗 题目链接
👉 https://leetcode.cn/problems/delete-operation-for-two-strings/
📖 内容概要
给定两个字符串 word1 和 word2,每一步可以对 任意一个字符串删除一个字符 。
求使两个字符串 完全相同 所需的 最少删除步数。
✅ 只允许删除
✅ 不允许插入、替换
✅ 本质是 最长公共子序列(LCS)的变形
💡 解题思路(核心)
一、关键转化(最重要)
要让两个字符串相同,
最优策略是保留它们的最长公共子序列(LCS)。
需要删除的字符数 =
len(word1) + len(word2) − 2 × LCS
二、DP 状态定义
java
dp[i][j] =
将 word1 前 i 个字符
和 word2 前 j 个字符
变成相同所需的最少删除次数
🔁 状态转移(重点讲解)
✅ 情况 1:当前字符相同
java
if (w1[i-1] == w2[j-1]) {
dp[i][j] = dp[i-1][j-1];
}
- 两个字符都保留
- 不需要删除
- 直接继承之前的结果
❌ 情况 2:当前字符不同
有三种删除策略:
| 操作 | 状态转移 | 删除次数 |
|---|---|---|
删除 word1[i] 和 word2[j] |
dp[i-1][j-1] + 2 |
各删 1 |
只删除 word1[i] |
dp[i-1][j] + 1 |
1 |
只删除 word2[j] |
dp[i][j-1] + 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(
dp[i - 1][j - 1] + 2, // 两边都删
Math.min(
dp[i - 1][j] + 1, // 删 word1[i]
dp[i][j - 1] + 1 // 删 word2[j]
)
);
}
}
}
return dp[len1][len2];
}
}
⏱️ 复杂度分析
| 指标 | 复杂度 |
|---|---|
| 时间复杂度 | O(len1 × len2) |
| 空间复杂度 | O(len1 × len2) |
🔍 与 LCS 解法的关系
| 解法 | 思路 |
|---|---|
| LCS 解法 | 先求公共子序列,再算删除次数 |
| 本题 DP | 直接建模删除代价 |
两者结果 完全等价:
dp[len1][len2] = len1 + len2 − 2 × LCS
也可以直接用LCS代码来通过此题:
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];
int res = 0;
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] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
res = Math.max(res,dp[i][j]);
}
}
return len1+len2-2*res;
}
}