剑指 Offer 59 队列的最大值、滑动窗口的最大值

本文介绍了如何利用双向队列和单调队列解决滑动窗口最大值及队列最大值问题。通过不断更新队列,保持队列头部始终为当前窗口或队列的最大值,从而在O(1)的时间复杂度内完成查询操作。具体实现包括在窗口滑动时删除队列首部元素,在队列末尾添加新元素并维护最大值。

剑指 Offer 59 - I. 滑动窗口的最大值(困难)

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

剑指Offer 30. 包含 min 函数的栈 ,其使用 单调栈 实现了随意入栈、出栈情况下的 O(1) 时间获取 “栈内最小值” 。本题同理,不同点在于 “出栈操作” 删除的是 “列表尾部元素” ,而 “窗口滑动” 删除的是 “列表首部元素” 。

双向队列

在这里插入图片描述
在这里插入图片描述

到这应该可以动手实现了。

只要加入的值比现有的都大,窗口往右移,该窗口的最大值就不受该值前面的元素影响,所以可以把前面的元素移除队列。

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        from collections import deque
        if not nums or k==0: return [] 
        i, j, end = 0, 0, len(nums)
        top = deque()
        res = []
        while j<k: # 未形成窗口
            while top and top[-1]<nums[j]:
                top.pop()
            top.append(nums[j])
            j += 1
        res.append(top[0])
        while j<end:  # 形成窗口后
            left = nums[i]
            if left == top[0]:
                top.popleft()
            i += 1
            while top and top[-1]<nums[j]:
                top.pop()
            top.append(nums[j]) # 先加入新元素 再判断窗口最大值
            res.append(top[0])
            j += 1
        return res

剑指 Offer 59 - II. 队列的最大值

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1

1队列+1双端队列
self.queue = queue.Queue()
self.deque = queue.deque()
两个类的区别,队列不能判断为not b,也不能下标索引

class MaxQueue:
    from collections import deque
    def __init__(self):
        self.de = deque()
        self.top = deque()

    def max_value(self) -> int:
        if not self.de: return -1
        return self.top[0]

    def push_back(self, value: int) -> None:
        while self.top and self.top[-1] < value:
            self.top.pop()
        self.top.append(value)
        self.de.append(value)

    def pop_front(self) -> int:
        if not self.de: return -1
        out = self.de.popleft()
        if self.top[0] == out:
            self.top.popleft()
        return out

# Your MaxQueue object will be instantiated and called as such:
# obj = MaxQueue()
# param_1 = obj.max_value()
# obj.push_back(value)
# param_3 = obj.pop_front()

官方题解,思想是一样的

import queue
class MaxQueue:
    """1队列+1双端队列"""
    def __init__(self):
        self.queue = queue.Queue()
        self.deque = queue.deque()

    def max_value(self) -> int:
        if self.deque:
            return self.deque[0]
        else:
            return -1
        # return self.deque[0] if self.deque else -1 或者这样写

    def push_back(self, value: int) -> None:
        while self.deque and self.deque[-1] < value:
            self.deque.pop()
        self.deque.append(value)
        self.queue.put(value)
        

    def pop_front(self) -> int:
        if not self.deque: return -1
        ans = self.queue.get()
        if ans == self.deque[0]:
            self.deque.popleft()
        return ans

作者:z1m
链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/ru-he-jie-jue-o1-fu-za-du-de-api-she-ji-ti-by-z1m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值