剑指 Offer 59 - I. 滑动窗口的最大值

题目链接

题目描述

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 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

在这里插入图片描述

解题思路

利用优先级队列来进行求解
创建一个pair<int,int>p来存储输入向量中每个元素的值和索引。
创建一个优先级队列“q”,根据它们的值按降序存储对“p”。

首先遍历输入向量中的前k个元素,并将每对 “p” 添加到优先级队列 “q” 中。
通过检索优先级队列“q”中具有最大值的顶部元素的值,获得第一个子数组的最大值。
然后开始滑动窗口:
通过一次向右滑动窗口一个元素来遍历输入向量中的剩余元素。
从索引小于或等于当前子数组的左边界的优先级队列“q”中删除所有对“p”。这样可以确保优先级队列中的最大值始终在当前子数组(窗口)中。
将当前元素添加到优先级队列“q”中。 通过检索优先级队列“q”中顶部元素的值,获得当前子数组的最大值。
滑动窗口,直到到达输入数组的末尾。
总之,该函数使用优先级队列来有效地找到输入向量中长度为k的每个滑动窗口中的最大值。

AC代码如下:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>ans;
        pair<int, int>p;
        priority_queue<pair<int, int>>q;
        for(int i = 0; i < k; i++) q.push(make_pair(nums[i], i));
        ans.push_back(q.top().first);
        int left = 0, right = k;
        while(right < nums.size()) {
            while(!q.empty() && q.top().second <= left) q.pop();
            q.push(make_pair(nums[right], right));
            left++, right++;
            ans.push_back(q.top().first);
        }
        return ans;
    }
};

扩展一下,找滑动窗口最小值

有了上述思路,寻找滑动窗口最小值便变得非常简单,我们可以通过自定义优先级队列的的优先级即可,也就是说值越小优先级越高。
可以通过重载运算符 “<” 来自定义priority_queue的优先级。具体来说,如果我们想要在队列中按照第一个元素的大小升序定义优先级,则可以这样实现:

struct cmp {
    bool operator() (const pair<int, int>& a, const pair<int, int>& b) {
        return a.first > b.first;
    }
};

priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> q;

通过重载运算符 “<” 来自定义priority_queue的优先级。其中,结构体cmp重载了小于号运算符,使得在队列中按照pair的第一个元素的大小定义优先级,第一个元素越小优先级越高。注意,这里的第二个参数是一个vector,表示底层容器的类型,第三个参数是一个比较器,表示优先级的比较方式。
在优先级队列中,自定义排序cmp的作用看上去似乎和sort中的自定义排序相反了。其原因在于优先级队列本身默认的规则就是优先级高的放在队首,因此把小于号重载为大于号的功能时只是把这个规则方向了一下。因此要记住优先队列的这个函数与sort中的cmp函数的效果是相反的。

全部代码如下:

class Solution {
public:
    struct cmp {
        bool operator() (const pair<int, int>& a, const pair<int, int>& b) {
            return a.first > b.first;
        }
    };
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>ans;
        pair<int, int>p;
        priority_queue<pair<int, int>, vector<pair<int, int>>, cmp>q;
        for(int i = 0; i < k; i++) q.push(make_pair(nums[i], i));
        ans.push_back(q.top().first);
        int left = 0, right = k;
        while(right < nums.size()) {
            while(!q.empty() && q.top().second <= left) q.pop();
            q.push(make_pair(nums[right], right));
            left++, right++;
            ans.push_back(q.top().first);
        }
        return ans;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值