滑动窗口-最小覆盖字串
如题:给定两个字符串 s 和 t 。返回 s 中包含 t 的所有字符的最短子字符串。如果 s 中不存在符合条件的子字符串,则返回空字符串 “” 。如果 s 中存在多个符合条件的子字符串,返回任意一个。
滑动窗口方案:
var minWindow = function (s, t) {
if (!s || !s.length || !t || !t.length) return "";
const len1 = t.length,
len2 = s.length;
const rObj = {};
for (const c of t) {
rObj[c] = (rObj[c] || 0) + 1;
}
let required = len1;
let minStr = "";
let minLen = Number.MAX_VALUE;
let left = 0;
for (let i = 0; i < len2; i++) {
const cur = s[i];
if (rObj[cur] !== void 0) {
if (rObj[cur]-- > 0) required--;
}
while (left < i && (rObj[s[left]] === void 0 || rObj[s[left]] < 0)) {
if (rObj[s[left]] < 0) rObj[s[left]]++;
left++;
}
const len = i - left + 1;
if (required == 0) {
if (len < minLen) {
minStr = s.slice(left, i + 1);
minLen = len;
}
const leftChar = s[left++];
if (rObj[leftChar] != void 0) {
rObj[leftChar]++;
required++;
}
}
}
return minStr;
};
优化:
使用更直观的变量名
优化滑动窗口收缩逻辑
简化条件判断
修复边界情况处理
使用现代 JavaScript 语法
var minWindow = function (s, t) {
if (!s.length || !t.length) return "";
const required = new Map(); // 需要匹配的字符计数
for (const c of t) {
required.set(c, (required.get(c) || 0) + 1);
}
let needCount = t.length; // 需要匹配的总字符数
let minStr = ""; // 最小窗口字符串
let minLen = Infinity; // 最小窗口长度
let left = 0; // 滑动窗口左边界
for (let right = 0; right < s.length; right++) {
const char = s[right];
// 处理当前字符
if (required.has(char)) {
const count = required.get(char);
if (count > 0) needCount--; // 当字符仍有需求时才减少needCount
required.set(char, count - 1);
}
// 当窗口满足条件时,尝试收缩左边界
while (needCount === 0) {
const currentLen = right - left + 1;
// 更新最小窗口
if (currentLen < minLen) {
minLen = currentLen;
minStr = s.slice(left, right + 1);
}
// 移动左边界并恢复状态
const leftChar = s[left];
if (required.has(leftChar)) {
required.set(leftChar, required.get(leftChar) + 1);
if (required.get(leftChar) > 0) needCount++;
}
left++;
console.log('left,right==>', left,right);
}
}
return minLen === Infinity ? "" : minStr;
};