Hot100-Day56-T239滑动窗口最大值

0 阅读2分钟

Day56[26/3/27]T239滑动窗口最大值

给你一个整数数组 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]

提示:

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

解题思路

需要维护一个双端队列,这个双端队列按照元素大小降序排列,且这个队列最长为 k。

然后每次扫描到新的元素的时候,就存入到队列中,并且这个存入是有讲究的,从队列尾部开始找,所有比这个新元素小的元素全部弹出。然后因为这个队列是降序排列的,所以每次取队头就是窗口最大元素了。

但是还需要考虑一个点,就是必须把元素的下标存一下,如果发现队头元素虽然大,但是下标已经过期了(也就是当前的滑动窗口正好滑出了这个下标)那么必须把这个队头元素弹出。

建议配合 B 站视频进行理解。

Code

#include <iostream>
#include <vector>
#include <deque>
using namespace std;

class Solution
{
public:
    vector<int> maxSlidingWindow(vector<int> &nums, int k)
    {
        // 防止尺寸问题
        if (nums.size() + 1 - k <= 0)
        {
            return {};
        }

        vector<int> res(nums.size() + 1 - k);
        deque<pair<int, int>> window;

        // 递减队列初始化
        for (int i = 0; i < k; i++)
        {
            while (window.size() && window.back().first < nums[i])
            {
                window.pop_back();
            }
            window.push_back({nums[i], i});
        }

        // 开始找窗口最大
        res[0] = window.front().first;
        for (int i = 1; i < res.size(); i++)
        {
            int num = nums[i + k - 1];

            // 需要考虑更新问题(下标太旧的需要被抛弃)
            if (window.front().second == i - 1)
            {
                window.pop_front();
            }
            while (window.size() && window.back().first < num)
            {
                window.pop_back();
            }
            window.push_back({num, i + k - 1});

            res[i] = window.front().first;
        }

        return res;
    }
};

auto main() -> int
{
    cout << "Hello World!" << endl;
}