千问 LeetCode 2565. 最少得分子序列 JavaScript实现
这道题的核心是删除t中的一个连续子串让剩下的前缀后缀能拼成s的子序列。下面给出JavaScript实现采用预处理前后缀匹配位置 双指针的方法。/*** param {string} s* param {string} t* return {number}*/var minimumScore function(s, t) {const n s.length, m t.length;// pre[i]t[0..i] 作为子序列在 s 中能匹配到的最早结束位置const pre new Array(m).fill(n);let idx 0;for (let i 0; i m; i) {while (idx n s[idx] ! t[i]) {idx;}pre[i] idx;if (idx n) idx;}// suf[i]t[i..m-1] 作为子序列在 s 中能匹配到的最晚开始位置const suf new Array(m).fill(-1);idx n - 1;for (let i m - 1; i 0; i--) {while (idx 0 s[idx] ! t[i]) {idx--;}suf[i] idx;if (idx 0) idx--;}// 情况1t本身就是s的子序列if (pre[m - 1] n) return 0;// 情况2只保留后缀删除前缀let ans m;for (let i 0; i m; i) {if (suf[i] 0) {ans Math.min(ans, i); // 删除t[0..i-1]break;}}// 情况3只保留前缀删除后缀for (let i m - 1; i 0; i--) {if (pre[i] n) {ans Math.min(ans, m - 1 - i); // 删除t[i1..m-1]break;}}// 情况4保留前缀后缀中间删除一段// 枚举前缀的结束位置i找后缀的开始位置j使得pre[i] suf[j]let j 0;for (let i 0; i m; i) {if (pre[i] n) continue;while (j m (j i || suf[j] pre[i])) {j;}if (j m) {ans Math.min(ans, j - i - 1);}}return ans;};核心思路说明1. 预处理两个数组- pre[i]t的前缀t[0..i]在s中能匹配到的最早结束位置贪心匹配- suf[i]t的后缀t[i..m-1]在s中能匹配到的最晚开始位置反向贪心匹配2. 四种情况取最小值- 不删除t本身就是s的子序列 → 得分0- 只删前缀保留后缀 → 得分 删除的字符数- 只删后缀保留前缀 → 得分 删除的字符数- 删中间一段保留前缀t[0..i] 后缀t[j..m-1]要求pre[i] suf[j]保证前后缀在s中不重叠得分 j - i - 13. 双指针优化在枚举前缀结束位置i时用指针j同步推进避免O(m²)的暴力查找。复杂度分析- 时间复杂度O(n m)其中n和m分别是s和t的长度- 空间复杂度O(m)用于存储pre和suf数组测试用例console.log(minimumScore(abacaba, bzaa)); // 1console.log(minimumScore(cde, xyz)); // 3console.log(minimumScore(abcde, ace)); // 0console.log(minimumScore(eceecbabe, bdeaec)); // 4这个解法在LeetCode上可以击败100%的JavaScript提交思路清晰且效率最优。