Python返回滑动窗口中的最大值 LeetCode NO.239

32 篇文章 1 订阅
8 篇文章 0 订阅


之前博客写过一道关于大顶堆小顶堆的优先队列,Python 返回数据流中的第k大元素 LeetCode NO.703。这题也可以用这种方法很好的求解。
思路:

  1. 我们可以来维护k大小的大顶堆。这个堆顶的元素就是最大值。可以想到我们对堆进行就可以得最后的结果。举个栗子?,维护一个【1,3,-1】这样的大顶堆,堆顶3,然后先删除最左边的元素,然后加入-3,调整大顶堆的元素。复杂度很容算出来就是O(N log k)
# 思路1
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        import heapq
        if not nums: return []
        window,result = list(),list()
        for i,x in enumerate(nums):
            window.append(x)
            if len(window) == k:
                result.append(heapq.nlargest(1,window)[0])
                window = window[1:]
        return result
  1. 那么如何把复杂度降低到线性的呢。由于k的值是给定的,也就是程序运行开始,到结束k不变。那么我们可以来维护这样一个队列,左边出右边进。并且当进来的元素的时候,我们需要让最左边的元素始终为最大的那个。举个栗子?,一开始为【1】添加,【1,3】,维护,【3】,添加【3,-1】,维护,不发生变化,添加【3,-1,-3】,维护不发生变化,添加【-1,-3,5】,维护【5】。通过代码可以,维护一个window的时候,可以大致认为为平均下来为O(1),那么整体就是一个线性复杂度。
#思路2
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        if not nums: return []
        window, result = list(),list()
        for i,x in enumerate(nums):
        	#使得window窗口一直为k,注意window里面存的是index
            if i >= k  and window[0] <= i-k:
                window.pop(0)
            #维护队列,使得最左边的元素为最大值
            while window and nums[window[-1]] <= x:
                window.pop()
            window.append(i)
            if i >= k-1:
                result.append(nums[window[0]])
        return result
  1. 其实看到题目的时候,也会想到使用动态规划,但是怎写是个问题。以下是LeetCode的解析,提供一种思路。



#思路3,太巧妙了,除非面试出现原题,反正我是想不出来
class Solution:
    def maxSlidingWindow(self, nums: 'List[int]', k: 'int') -> 'List[int]':
        n = len(nums)
        if n * k == 0:
            return []
        if k == 1:
            return nums
        
        left = [0] * n
        left[0] = nums[0]
        right = [0] * n
        right[n - 1] = nums[n - 1]
        for i in range(1, n):
            # from left to right
            if i % k == 0:
                # block start
                left[i] = nums[i]
            else:
                left[i] = max(left[i - 1], nums[i])
            # from right to left
            j = n - i - 1
            if (j + 1) % k == 0:
                # block end
                right[j] = nums[j]
            else:
                right[j] = max(right[j + 1], nums[j])
        
        output = []
        for i in range(n - k + 1):
            output.append(max(left[i + k - 1], right[i]))
            
        return output
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值