算法通关村第十六关-青铜挑战滑动窗口思想

大家好我是苏麟 , 今天来说说滑动窗口思想 .

我们在数组和链表部分研究过双指针思想,这里我们继续学习滑动窗口思想。滑动窗口其实是双指针思想的一种特殊场景,由于这种方式能够很好的解决一些特定场景的问题,因此就有了“滑动窗口思想”

什么是窗口、什么是窗口的滑动 :

  • 窗口: 窗口其实就是两个变量left和right之间的元素,也可以理解为一个区间。窗口大小可能固定,也可能变化,如果是固定大小的,那么自然要先确定窗口是否越界,再执行逻辑处理。如果不是固定的,就要先判断是否满足要求,再执行逻辑处理。
  • 滑动: 说明这个窗口是移动的,事实上移动的仍然是left和right两个变量,而不是序列中的元素。当变量移动的时,其中间的元素必然会发生变化,因此就有了这种不断滑动的效果。

看下图 :

算法通关村第十六关-青铜挑战滑动窗口思想_第1张图片

这就是一个滑动窗口 , 窗口慢慢向右 .

入门题目

最长连续递增序列

描述 :

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 rl < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

题目 :

LeetCode 674.最长连续递增序列 :

674. 最长连续递增序列

分析 :

为了方便演示,我们给个示例(1,3,5,4,7,8,9,2),则图示如下,题目要求找到最长的连续递增子序列。

可以看到,最长递增子序列为{4,7,8,9)所以应该返回 4。所以在遍历的时候,我们可以从第 2 个元素开始先定义[left,right]的区间来表示当前的递增区间,执行如下操作:

  • 如果当前遍历到的元素比它左边的那一个元素要严格大,right就增加
  • 否则就将left跳到right的起始位置,重新开始计算

解析 :

class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int left = 0;
        int right = 0;
        int res = 0;
        while(right < nums.length){
            if(right > 0 && nums[right-1]>=nums[right]){
                left = right;
            }
            right++;
            res = Math.max(res,right-left);
        }
        return res;
    }
}

子数组最大平均数 I

描述 :

给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。

请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。

任何误差小于 10-5 的答案都将被视为正确答案。

题目 :

LeetCode 643.子数组最大平均数 ::

643. 子数组最大平均数 I

分析 :

这是典型的滑动窗口,大小都规定了,就是K,那我们只要先读取k个,然后逐步让窗口向前走就可以了 .

解析 :

class Solution {
    public double findMaxAverage(int[] nums, int k) {
        double num = 0.0;
        int left = 0;
        for(int i = 0; i < k;i++){
            num += nums[i];
        }
        double max = num;
        for(int right = k;right < nums.length; right++){
            num += nums[right] - nums[right - k];
            max = Math.max(max,num);
        }
        return max / k;
    }
}

这期就到这里 , 下期见!

你可能感兴趣的:(算法村,算法,leetcode,数据结构,java,开发语言)