使用滑动窗口,双指针解决问题
最小覆盖子串【leetcode-76】
题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。 如果 s 中存在这样的子串,我们保证它是唯一的答案。
运行效率
代码如下
function minWindow(s: string, t: string): string {
const [tset, tmap] = initT(t);
const str = initS(s, tset);
//测试str
// console.log("----test----", testT(str, s));
let res: [number, number] = [0, Infinity];
let temp = new Map();
let okCount = 0;
let pre = 0;
let end = 0;
while (end < str.length) {
while (okCount !== tset.size && end < str.length) {
const key = s.charAt(str[end]);
temp.set(key, (temp.get(key) ?? 0) + 1);
if (temp.get(key) === tmap.get(key)) {
okCount++;
}
end++;
}
while (okCount === tset.size && pre < end) {
const key = s.charAt(str[pre]);
temp.set(key, temp.get(key) - 1);
if (temp.get(key) < tmap.get(key)) {
//记录结果
res =
res[1] - res[0] > str[end - 1] - str[pre]
? [str[pre], str[end - 1] + 1]
: res;
okCount--;
}
pre++;
}
}
return res[1] === Infinity ? "" : s.substring(res[0], res[1]);
function initS(s: string, tSet: Set<string>): number[] {
const str: number[] = [];
for (let i = 0; i < s.length; i++) {
const key = s.charAt(i);
if (tSet.has(key)) {
str.push(i);
}
}
return str;
}
function initT(t: string): [Set<string>, Map<string, number>] {
const set = new Set<string>();
const map = new Map();
for (let i = 0; i < t.length; i++) {
const key = t.charAt(i);
map.set(key, (map.get(key) ?? 0) + 1);
set.add(key);
}
return [set, map];
}
}
function testT(str: number[], s: string) {
return str.reduce((acc, i) => acc + s.charAt(i), "");
}
const res = minWindow("ADOBECODEBANC", "ABC");
const res1 = minWindow("a", "a");
const res2 = minWindow("a", "aa");
const res3 = minWindow("ab", "a");
debugger;