力扣hot10---大根堆+双端队列

题目:

大根堆思路:

维护最大值,应该首先想到大根堆。C++中对应着priority_queue,这里用pair<int,int>来记录对应的值和在nums中的索引。所以有priority_queue<pair<int,int>> q。在大根堆中,用q.top().first即可获取最大值。对于滑动窗口有三个步骤:处理进入的元素、处理出去的元素、记录结果。直接看代码吧,很清晰的。

大根堆代码

C++代码

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        //大根堆
        priority_queue<pair<int,int>> q;
        //初始化大根堆
        for(int i=0;i<k;i++){
            q.emplace(nums[i],i);
        }
        //初始化res
        vector<int> res={q.top().first};
        //处理后续窗口
        int len=nums.size();
        for(int i=k;i<len;i++){
            //进入
            q.emplace(nums[i],i);
            //出去
            while(q.top().second<=i-k){
                q.pop();
            }
            //记录答案
            res.push_back(q.top().first);
        }
        return res;
    }
};

对于priority_queue,增添元素为emplace,删除元素为pop。

定义小根堆的话(C++默认大根堆),需要把代码:

priority_queue<pair<int,int>> q;

转换为:(或者直接对元素取负就行)

priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;

python代码:

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        q=[]
        for i in range(k):
            heapq.heappush(q,(-nums[i],i))
        res=[-q[0][0]]
        len_nums=len(nums)
        for i in range(k,len_nums):
            heapq.heappush(q,(-nums[i],i))

            while q[0][1]<=i-k:
                heapq.heappop(q)
            res.append(-q[0][0])
        return res

注意,python中默认的是小根堆 ,需要导入包import heapq

对于加入元素操作:

heapq=[]
heapq.heappush(q,(-nums[i],i))

删除元素操作:

heapq.heappop(q)

双端队列思想:

  1. 滑动窗口加入元素
    每当从末端加入一个元素时,都要跟双端队列的末尾元素进行比较,如果末尾的元素更小,当加入该元素后,末尾元素一定不是最大值,所以在加入该元素之前,将末尾元素pop掉(这里运用while循环)。
  2. 滑动窗口移出元素

    加入该元素后,还要判断双端队列最开始的元素的索引是否在要求的滑动窗口中,如果不在,那需要把最前面的元素pop掉(while循环)。

  3. 记录答案

    可以考虑到这是一个递减的双端队列,所以最大值永远是第一个元素。

双端队列代码:

C++代码:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int len=nums.size();
        //只记录数组索引的双端队列
        deque<int> q;
        //初始化双端队列
        for(int i=0;i<k;i++){
            while(!q.empty() && nums[q.back()]<=nums[i]){
                q.pop_back();
            }
            q.push_back(i);
        }
        //初始化答案
        vector<int> res={nums[q.front()]};
        //滑动窗口---进入/移出/记录答案
        for(int i=k;i<len;i++){
            //进入
            while(!q.empty() && nums[q.back()]<=nums[i]){
                q.pop_back();
            }
            q.push_back(i);
            //移出
            while(q.front()<=i-k){
                q.pop_front();
            }
            //记录答案
            res.push_back(nums[q.front()]);
        }
        return res;
    }
};

python代码:

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        len_nums=len(nums)
        q=deque()
        for i in range(k):
            while q and nums[q[-1]]<=nums[i]:
                q.pop()
            q.append(i)
        res=[nums[q[0]]]
        for i in range(k,len_nums):
            while q and nums[q[-1]]<=nums[i]:
                q.pop()
            q.append(i)
            while q[0]<=i-k:
                q.popleft()
            res.append(nums[q[0]])
        return res
        

注意需要引入头文件from collections import deque

q=deque()
C++:q.back()
python:q[-1]
#双端队列deque插入/删除元素
q.append(i)
q.pop()
q.popleft()

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值