滑动窗口与单调队列

滑动窗口

滑动窗口的窗口就是一个区间,滑动窗口就是遍历每一个区间。

力扣最大区间平均数

实际就是求定长区间和,这是滑动窗口最简单的题目,只需要实现窗口移动即可

class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        double sum = 0;
        int n =nums.size();
        for(int i = 0;i < k;++i){
            sum +=nums[i];
        }
        double ans = sum;
        for(int i = k;i < n;++i){
            sum -=nums[i - k];
            sum +=nums[i];
            ans = max(ans,sum);
        }
        return ans / k;
    }
};

变长窗口

窗口不一定是定长的,滑动窗口也可以用于求最长连续区间

力扣最大连续1个数

给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,求操作后 数组中连续 1 的最大个数 。

实际是就是找一个区间,区间内有不多于k个0,找最长区间。

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int ans = 0,l = 0,n = nums.size(),s0 = 0;
        for(int i = 0;i < n;++i){
            if(nums[i] == 0){++s0;}
            while(s0 > k){
                if(nums[l] == 0){
                    --s0;
                }
                ++l;
            }
            ans = max(ans,i - l + 1);
        }
        return ans;
    }
};

以上类型的滑动窗口所求最值都是只关注入出窗口的,不需要考虑窗口内部性质,如果要求窗口内的最值,就需要用到单调队列。

双端队列 deque deque 支持在队头和队尾高效地进行插入和删除操作,非常适合实现单调队列。

借助双端队列存储数据,兼顾「双端 O (1) 操作」和「随机访问 O (1)」。

 单调队列:

        单调队列是一种特殊的队列数据结构,队列中的元素始终保持单调递增或单调递减的特性。它主要用于高效解决一些区间最值问题,特别是在滑动窗口场景下,能够将原本需要O(nk) ( n为数组长度, k为窗口大小)的时间复杂度优化到O(n) 。

窗口内最值

leetcode滑动窗口中的最大值

求窗口最值就是裸单调队列。

  • 确保队首为当前最值
  • 队首后面单调,队首后为次最值
  • 新元素入队如果能比较过队尾,弹出队尾来维护单调(被弹出元素早于新元素离开窗口,后续也用不到被弹元素了)
  • 队首离开窗口时出队

为了方便出队一般队列都存储索引

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> q;
        vector<int> ans;
        for(int i = 0;i < nums.size();++i){
            while(!q.empty() && nums[q.back()] <= nums[i]){
                q.pop_back();
            }
            q.push_back(i);
            if(q.front() < i - k + 1){q.pop_front();}
            if(i >= k - 1){ans.push_back(nums[q.front()]);}
        }
        return ans;
    }
};
posted @ 2025-11-21 18:38  mc12356  阅读(6)  评论(0)    收藏  举报  来源