最近刷题看到字符串和数组相关的题目很多都有这个滑动窗口,但我对滑动窗口的印象还停留在TCP的滑动窗口,赶紧补一下这块知识。
什么是滑动窗口
滑动窗口算法也叫双指针算法,多用于特定大小的数组或字符串,使用一个大小可变动的“窗口”,按固定方向滑动,遍历字符串或数组,寻找其中符合要求的部分。从而降低循环嵌套的深度,压低了复杂度,某种程度上说是空间换时间的办法,
滑动窗口不能算某种固定的Function,更接近于一种办法。
怎样构建滑动窗口
- 滑动: 说明这个窗口是移动的,也就是移动是按照一定方向来的。
- 窗口: 窗口大小并不是固定的,可以不断扩容直到满足一定的条件;也可以不断缩小,直到找到一个满足条件的最小窗口;当然也可以是固定大小。
具体步骤
- 我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个「窗口」。
- 我们先不断地增加 right 指针扩大窗口 [left, right],直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
- 此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。
- 重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。
练习
LeetCode 15 三数之和
描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
解题
比起两数之和,这道题用滑动窗口解题的前提是数组已排序
var threeSum = function(n) {
const target = 0;
let result = [];
// 对原数组从大到小排序
let nums = n.sort((a,b) =>{return a-b});
// 指定 a
for(let i=0; i<nums.length-1; i++){
// 设置左右双指针,从nums两端开始,寻找符合要求的b,c
let left = i+1;
let right = nums.length - 1;
// 当左右双指针相遇,本次搜索结束
while(left < right){
let sum = nums[i] + nums[left] + nums[right];
// 发现符合要求的三数之和
if(sum === target){
result.push([nums[i],nums[left],nums[right]]);
console.log(nums[i],nums[left],nums[right])
left ++;
}
else{
// 和偏小,指针右移扩大数值
if(sum < target){
left ++;
continue;
}
// 和偏大,指针左移减小数值
else if(sum > target){
right --;
continue;
}
}
}
}
console.log(result)
};