1.滑动窗口的定义
滑动 : 窗口可以按某个方向移动
窗口 :窗口大小可以固定,也可以不固定,此时可以向外或者向内,扩容或者缩小窗口直至满足条件。
2.滑动窗口的应用
一两道具体的力扣算法题来说明。
LeetCode 209:长度最小的子数组
核心思想:
(1)创建一个可以滑动的窗口,但是这个窗口的大小是不断变化的
(2)设置两个指针来控制边界,left 指针对应左边界, right 右边界对应右边距
(3)遍历整个数组,当窗口中元素和小于目标值时,右边的指针向右移动一次;如果元素和大于等于目标值时,获得当前窗口的大小,并将左边的指针向右移动一此。
(4)对于遍历数组通过循环来完成,移动左指针时也通过循环来完成,因为要获取最短长度,因为左边移动一次可能还不是最短,所以这部分的操作也通过循环来完成。
(5)最后返回最小的窗口大小。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//设置滑动窗口的指针
int left = 0;
int right = 0;
//设置窗口内元素的总和与窗口大小
int sum = 0;
int len = Integer.MAX_VALUE;
//设置循环遍历数组
for(; right < nums.length; right++){
sum += nums[right];
//判断是否满足条件
while(sum >= target){
len = Math.min(len, right - left + 1);
sum -= nums[left];
left++;
}
}
return len == Integer.MAX_VALUE ? 0 : len;
}
}
LeetCode 209:滑动窗口最大值
知识点补充:
(1) 此题选择的解法应用到了双端队列:队列的两端都可以进行入队和出队的操作。
(2) 待补充
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//特殊情况处理
if(nums == null || nums.length < 2) return nums;
//双端队列保存窗口中最大值的位置
LinkedList<Integer> queue = new LinkedList();
//创建一个结果数组
int [] result = new int [nums.length - k + 1];
//循环遍历数组
for(int i = 0; i < nums.length; i++){
//保证队列从大到小
while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]) {
queue.pollLast();
}
//添加当前元素的位置到队列
queue.addLast(i);
//判断当前队列中队首元素是否有效
if(queue.peek() <= i - k){
queue.poll();
}
//当前窗口长度为k时保存最大值
if(i + 1 >= k){
result[i - k + 1] = nums[queue.peek()];
}
}
return result;
}
}