【LeetCode】239 and 1122(单调队列解决滑动窗口问题)

单调队列,相较于普通队列区别在于,队列中元素是单调排列的。

239. 滑动窗口最大值

在这里插入图片描述
该题一个直观解法是,每步移动后,对滑动窗口进行遍历,找出最大值,但该找最大值操作复杂度为O(k),会超时。因此,如何能达到O(1)复杂度找到最大值是我们的目标。
我们可以想到,对于两个相邻(只差了一个位置)的滑动窗口,它们共用着 k-1 个元素,而只有 1 个元素是变化的。我们可以根据这个特点进行优化。这可以用单调队列来求解。
解法:单调队列
单调队列,即维护队列中的队头至队尾元素单调递减。实现核心为,每次在队尾添加元素前,将所有小于该元素的元素从队尾移除,这样队头元素即为当前窗口最大值。另外需要注意的一点是,窗口是滑动的,当队头元素到达窗口的左端,即下一状态被移出窗口,这时需要将该元素从队头移除。

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:

        # 
        queue = collections.deque()
        result = []
        # print(queue)
        for i in range(len(nums)):
            if i < k-1:
                while queue and queue[-1] < nums[i]:
                	queue.pop()
                queue.append(nums[i])
            else:
            	# 从队尾移除,保证队列内元素的单调性
                while queue and queue[-1] < nums[i]:
                    queue.pop()
                queue.append(nums[i])
                # 队头元素即为当前窗口最大值
                result.append(queue[0])
                # 队头元素在当前窗口左边界
                if nums[i-k+1] == queue[0]:
                    queue.popleft()
                # print(queue)
        return result

解法2:优先队列(最大堆)
在这里插入图片描述
该方法寻找最大值的时间复杂度为O(logn),具体可以参考官方解答

1122. 数组的相对排序

在这里插入图片描述
解法:自定义排序
可以自定义排序的比较规则,改为比较在arr2中元素对应索引大小。同时python中可以对元组进行比较,用于处理arr2中未出现元素,未出现元素按元素大小进行排序。

class Solution:
    def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
        def mycmp(x: int) -> (int, int):
            return (0, rank[x]) if x in rank else (1, x)
        
        rank = {x: i for i, x in enumerate(arr2)}
        arr1.sort(key=mycmp)
        return arr1

解法2:计数排序
在这里插入图片描述

class Solution:
    def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
        upper = max(arr1)
        frequency = [0] * (upper + 1)
        for x in arr1:
            frequency[x] += 1
        
        ans = list()
        for x in arr2:
            ans.extend([x] * frequency[x])
            frequency[x] = 0
        for x in range(upper + 1):
            if frequency[x] > 0:
                ans.extend([x] * frequency[x])
        return ans
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值