每日刷题第12天 2021.1.7
最短超串
- 难度:中等
- 方法:滑动窗口
题目
- 假设你有两个数组,一个长一个短,短的元素均不相同。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。
- 返回最短子数组的左端点和右端点,如有多个满足条件的子数组,返回左端点最小的一个。若不存在,返回空数组。
示例
输入:
big = [7,5,9,0,2,1,3,5,7,9,1,1,5,8,8,9,7]
small = [1,5,9]
输出: [7,10]
输入:
big = [1,2,3]
small = [4]
输出: []
提示
big.length <= 1000001 <= small.length <= 100000
解法
/**
* @param {number[]} big
* @param {number[]} small
* @return {number[]}
*/
var shortestSeq = function(big, small) {
// 处理数据
let map1 = new Map();
// 长数组的长度
let lenB = big.length;
// 短数组的长度
let lenS = small.length;
for (let i = 0; i < lenS; i++) {
if (map1.has(small[i])) {
map1.set(small[i], map1.get(small[i]) + 1);
}else {
map1.set(small[i], 1);
}
}
// console.log('处理后的数据集', map1);
// 开始指针
let start = 0;
// 结束指针
let end = 0;
// 存储最终的结果
let ans = [];
// 记录符合数据的长度
let len = 0;
// 新的map集合,存储遍历过程中存储的数字个数
let map2 = new Map();
// 临时比较数据
let tempt = Infinity;
// 标记变量,记录是否是第一次
let flag = true;
while (end < lenB) {
// 不符合要求,动end
if (map1.has(big[end])) {
// console.log('map2',map1.has(big[end]),'send',big[end],'end', end);
// map1中存在,map2记录
if (map2.has(big[end])) {
map2.set(big[end], map2.get(big[end]) + 1);
}else {
map2.set(big[end], 1);
}
// console.log('处理过后的map2', map2);
// 如果没有超过既定的值,就需要len++
if (map2.get(big[end]) <= map1.get(big[end])) {
len++;
console.log('len++',len);
}
// 打破循环,动start
while(len >= lenS) {
// console.log('执行打破循环',len,'start',start,'lenS',lenS);
// 长度相等,取结果
if (flag) {
// 是第一次
ans = [start, end];
tempt = Math.min(tempt, end - start + 1);
flag = false;
// console.log('首次记录结果', ans,tempt);
}else {
// 不是第一次
if(len == lenS && tempt > (end - start + 1)) {
ans = [start, end];
tempt = Math.min(tempt, end - start + 1);
// console.log('记录结果', ans,tempt);
}
}
// 存在,弹出就需要更改个数
if (map2.has(big[start])) {
map2.set(big[start], map2.get(big[start]) - 1);
}
// 如果map2中的值小于map1中的值,就len--
if (map2.get(big[start]) < map1.get(big[start])) {
len--;
}
start++;
}
}
end++;
// console.log('执行完成一次',len);
}
return ans;
};
附录
- 滑动窗口,一次AC