整体思路
1. 核心问题与转换
这段代码依然沿用了 '总和 - 最大公共子序列(LCS)权重' 的逆向思维策略。 核心公式保持不变: 最小删除和 = ( s1 总和 + s2 总和 ) − ( LCS 字符 ASCII 和 × 2 )
2. 算法优化:状态压缩(1D DP)
与上一版二维数组解法不同,这里使用了一维数组进行空间优化。
- 空间压缩原理:
在二维 DP 中,计算
dp[i][j]只需要用到上一行的数据dp[i-1][...]和当前行左边的数据dp[i][j-1]。f[j+1]在更新前,存储的是上一行对应位置的值(相当于dp[i-1][j])。f[j]在更新后,存储的是当前行左边位置的值(相当于dp[i][j-1])。- 难点:在于如何获取
dp[i-1][j-1](左上角的值)。因为在更新f[j+1]之前,f[j]已经被更新为当前行的值了。 - 解决方案:引入
pre变量,专门用来暂存上一行对角线位置的值。
- 逻辑流程:
- 初始化长度为
m + 1的数组f,初始全为 0(代表空串时的公共和)。 - 外层循环遍历
s1的字符x。 - 在内层循环开始前,初始化
pre = 0(代表第 0 列的左上角,即空前缀)。 - 内层循环遍历
s2的索引j:- 先用
temp保存f[j+1]的旧值(即下一轮需要的左上角值)。 - 根据
x和t[j]是否相等,利用pre、f[j+1](旧)、f[j](新)更新f[j+1]。 - 更新
pre = temp,为下一个位置做准备。
- 先用
- 初始化长度为
完整代码
class Solution {
public int minimumDeleteSum(String s1, String s2) {
// 1. 计算两字符串初始的总 ASCII 和
int sum = s1.chars().sum() + s2.chars().sum();
char[] s = s1.toCharArray();
char[] t = s2.toCharArray();
int m t.length;
[] f = [m + ];
( x : s) {
;
( ; j < m; j++) {
f[j + ];
(x == t[j]) {
f[j + ] = pre + x * ;
} {
f[j + ] = Math.max(f[j + ], f[j]);
}
pre = temp;
}
}
sum - f[m];
}
}

