剑指Offer59-I.滑动窗口的最大值 C++

1、题目描述

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
输入: 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、VS2019上运行

使用单调队列的方法
编程狂想曲的动画演示很清晰
注意:队列q存储的是元素索引值,而不是元素本身,是个双端队列

#include <iostream>
#include <vector>
#include <deque>

using namespace std;

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        deque<int> q; // 双端队列,这个是用来存储元素索引值的,而不是元素本身
        if (!k ||k>n) {//判断一下为空的情况
        return {};
    }

        // 初始化窗口
        for (int i = 0; i < k; ++i) {
            while (!q.empty() && nums[i] >= nums[q.back()]) {
                q.pop_back(); // 保持队列的单调性,从队尾移除较小的元素
            }
            q.push_back(i); // 将当前元素的索引加入队列
        }

        vector<int> ans = { nums[q.front()] }; // 存储每个窗口的最大值

        // 移动滑动窗口
        for (int i = k; i < n; ++i) {
            while (!q.empty() && nums[i] >= nums[q.back()]) {
                q.pop_back(); // 保持队列的单调性,从队尾移除较小的元素
            }
            q.push_back(i); // 将当前元素的索引加入队列

            while (q.front() <= i - k) {//i-q.front() >=k其实更好理解一些,元素的索引差超过k的值或者等于k的值
                q.pop_front(); // 如果队列的头部元素不在当前窗口中,从队头移除
            }
            ans.push_back(nums[q.front()]); // 将当前窗口的最大值加入结果向量
        }
        return ans;
    }
};

int main() {
    Solution solution;
    vector<int> nums = { 1, 3, -1, -3, 5, 3, 6, 7 };
    int k = 3;
    vector<int> result = solution.maxSlidingWindow(nums, k);
    for (int i = 0; i < result.size(); ++i) {
        cout << result[i] << " ";
    }
    cout << endl;
    return 0;
}

3、队列

  • 双端队列:对于这种一端既可以有元素入队,又有元素出队的队列,称之为双向队列
    1.push_back(element):将元素添加到队尾。
    2.push_front(element):将元素添加到队首。
    3.pop_back():从队尾删除一个元素。
    4.pop_front():从队首删除一个元素。
    5.back():返回队尾元素,不删除。
    6.front():返回队首元素,不删除。
    7.empty():检查双端队列是否为空。
    8.size():返回双端队列中元素的数量。
  • 单调队列:从队首到队尾单调递减或递增的队列称之为单调队列。

4、题目思路

  • 遍历给定数组中的元素,如果队列不为空且当前考察元素大于等于队尾元素,则将队尾元素移除。直到,队列为空或当前考察元素小于新的队尾元素;
  • 当队首元素的下标小于滑动窗口左侧边界left时,表示队首元素已经不再滑动窗口内,因此将其从队首移除。
  • 由于数组下标从0开始,因此当窗口右边界right+1大于等于窗口大小k时,意味着窗口形成。此时,队首元素就是该窗口内的最大值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值