• leedcode 239. 滑动窗口最大值(单调队列)


    题目描述

    难度:困难

    给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

    返回滑动窗口中的最大值。

     

    示例 1:

    输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
    输出:[3,3,5,5,6,7]
    解释:
    滑动窗口的位置                最大值
    ---------------               -----
    [1  3  -1] -3  5  3  6  7       3
     1 [3  -1  -3] 5  3  6  7       3
     1  3 [-1  -3  5] 3  6  7       5
     1  3  -1 [-3  5  3] 6  7       5
     1  3  -1  -3 [5  3  6] 7       6
     1  3  -1  -3  5 [3  6  7]      7
    示例 2:

    输入:nums = [1], k = 1
    输出:[1]
    示例 3:

    输入:nums = [1,-1], k = 1
    输出:[1,-1]
    示例 4:

    输入:nums = [9,11], k = 2
    输出:[11]
    示例 5:

    输入:nums = [4,-2], k = 2
    输出:[4]
     

    提示:

    1 <= nums.length <= 105
    -104 <= nums[i] <= 104
    1 <= k <= nums.length

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/sliding-window-maximum
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    输入:
    [1,3,1,2,0,5] 3
    输出:
    [3,2,2,5]
    预期结果:
    [3,3,2,5]

    题解

    • 双端单调队列 经典题
    • 想到了单调队列,具体怎么用,为什么对它有效不清楚。看懂了思路,能写出来。
    • 窗口一旦滑倒后面的数,后面的数一旦入队列,那么前面比当前这个数小的数就不可能是最大值了。比如  [1 3 -1 2 0 5 ],k=[4],一开始窗口 [1 3 -1 2],最大值是3,队列为 [ 3,2] ,为什么不是 [ 1 3 -1 2 ] 呢?因为窗口一旦滑到后面,有 3 在,就不可能 1 最大,1 没必要存在于队列中,同理,有 2 在 -1 后面,又比 -1 大,-1不可能是最大的数,-1也没必要存在队列中。这种特性就适合用单调队列。
    class Solution {
    public:
        vector<int> maxSlidingWindow(vector<int>& nums, int k) {
            deque<int>q;//双端单调队列 队列从大到小
            vector<int>ans;
            int n=nums.size();
            for(int i=0;i<k;i++){
                while(!q.empty()&&q.back()<nums[i]){//如果队尾比当前数小
                    q.pop_back();//把队尾的数删掉
                }
                q.push_back(nums[i]);//把当前数放入队尾
                
            }
            ans.push_back(q.front());//记录最大值 最大值总在队头
            for(int j=k;j<n;j++){//指向滑动窗口最后一个数的后一个数
                int i=j-k;//指向滑动窗口的第一个数
                if(q.front()==nums[i]){//如果窗口向右滑动 这个数又是最大值 
                    q.pop_front();//那就删除
                }
                while(!q.empty()&&q.back()<nums[j]){//同上 维护单调队列
                    q.pop_back();
                }
                q.push_back(nums[j]);//把当前数放入队尾
                ans.push_back(q.front());
            }
        return ans;
        }
    };

    • 其它解法,优先队列
    • 没考虑过
    class Solution {
    public:
        vector maxSlidingWindow(vector& nums, int k) {
            int n = nums.size();
            priority_queue> q;
            for (int i = 0; i < k; ++i) {
                q.emplace(nums[i], i);
            }
            vector ans = {q.top().first};
            for (int i = k; i < n; ++i) {
                q.emplace(nums[i], i);
                while (q.top().second <= i - k) {
                    q.pop();
                }
                ans.push_back(q.top().first);
            }
            return ans;
        }
    };
  • 相关阅读:
    CodeForces 347B Fixed Points (水题)
    CodeForces 347A Difference Row (水题)
    CodeForces 346A Alice and Bob (数学最大公约数)
    CodeForces 474C Captain Marmot (数学,旋转,暴力)
    CodeForces 474B Worms (水题,二分)
    CodeForces 474A Keyboard (水题)
    压力测试学习(一)
    算法学习(一)五个常用算法概念了解
    C#语言规范
    异常System.Threading.Thread.AbortInternal
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/15294558.html
Copyright © 2020-2023  润新知