每日刷题第9天 2021.1.4
含有所有字符的最短字符串
- 难度:困难
- 方法:双指针
题目
- 给定两个字符串 s 和 t 。返回 s 中包含 t 的所有字符的最短子字符串。如果 s 中不存在符合条件的子字符串,则返回空字符串 "" 。
- 如果 s 中存在多个符合条件的子字符串,返回任意一个。
- 注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
示例
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最短子字符串 "BANC" 包含了字符串 t 的所有字符 'A'、'B'、'C'
输入: s = "a", t = "a"
输出: "a"
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,因此没有符合条件的子字符串,返回空字符串。
提示
1 <= s.length, t.length <= 105s和t由英文字母组成
解法
/**
* @param {string} s
* @param {string} t
* @return {string}
*/
var minWindow = function(s, t) {
let map1 = new Map();
// 处理数据
for (let i = 0; i < t.length; i++) {
if (map1.has(t[i])) {
map1.set(t[i], map1.get(t[i]) + 1);
}else {
map1.set(t[i], 1);
}
}
// console.log('map1', map1);
// 开始指针
let start = 0;
// 结束指针
let end = 0;
// 新的记录集合
let map2 = new Map();
// 存储找到的符合的字符的长度
let len = 0;
// 记录成功的数据集合
let str = '';
// 判断长度
let minLen = Infinity;
// 记录最终结果
let ans = -1;
while (end < s.length) {
// 满足
if (map1.has(s[end])) {
// 记录下来
if (map2.has(s[end])) {
map2.set(s[end], map2.get(s[end]) + 1);
}else {
map2.set(s[end], 1);
}
// console.log('start',start,'end',end,'2end',map2.get(s[end]),'1end',map1.get(s[end]));
// len长度++,只有当map1中的值大于等于map2中的值
if (map2.get(s[end]) <= map1.get(s[end])) {
len++;
}
// console.log('len', len);
// 判断len的长度,是否达到标准,必定相同
if (len == t.length) {
// console.log('达到标准',len,'start',start,'end',end);
// 从start 到 end 存储成一个字符串进行输出
if (minLen >= (end - start + 1)) {
ans = start;
minLen = end - start + 1;
}
// 处理start,让start寻找打破标准后停止
while (start <= end) {
// console.log('minLen', minLen);
// 包含有start
if (map1.has(s[start])) {
map2.set(s[start], map2.get(s[start]) - 1);
// console.log('-1',map2.get(s[start]));
}else {
start++;
if (minLen >= (end - start + 1)) {
ans = start;
minLen = end - start + 1;
}
continue;
}
// 判断长度是否需要减少,打破了平衡标准
if (map2.get(s[start]) < map1.get(s[start])) {
// console.log('m2',map2.get(s[start]),'m1',map1.get(s[start]));
len--;
start++;
break;
}else {
start++;
if (minLen >= (end - start + 1)) {
ans = start;
minLen = end - start + 1;
}
}
}
}
end++;
}else {
// 不满足
end++;
}
}
if (ans == -1) {
return '';
}else {
let str = '';
for (let i = ans; i < ans + minLen; i++) {
str += s[i];
}
return str;
}
};
附录
- 双指针
- 思路对,还要将伪代码写出来