算法设计大赛T17

今天终于来到了第17题,也是第一道困难题目啦(偷偷吐槽句,题目给的真多…)

T239 滑动窗口最大值
给你一个整数数组 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

解题思路:
如果不考虑时间复杂度问题,这道题应该不算什么难题,对数组进行依次遍历即可。考虑时间复杂度的情况下,我们使用堆来解决。
取nums中前k个元素放入堆中,以[-nums[i], i]的形式进行储存;负号的意义在于使堆按大堆进行排序,而i为该元素的索引。依次取k+1到nums末尾的元素,将元素放入堆中重新排序,取出堆中的最大值放入res中。倘若滑动窗口已经划过堆中的最大元素,则将最大元素从堆中pop,直至找到堆中在滑动窗口内的最大元素,代码如下:

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        tr = [[-nums[i], i] for i in range(k)]
        heapq.heapify(tr)
        res = [-tr[0][0]]
        for i in range(k,len(nums)):
            heapq.heappush(tr, [-nums[i],i])
            while tr[0][1] <= i-k:
                heapq.heappop(tr)
            res.append(-tr[0][0])
        return res

运行结果:
在这里插入图片描述

这里再提出一种相较于暴力求len(nums)-k次更优的一种算法(虽然没过的了测试…)
取出前k个数的最大值后,将窗口依次向右滑动,若新进入的数比res中最后一个数大,则将新进入的nums[i]加入res,否则仍加入res[-1]。窗口没向右一格后将最左端元素pop,若pop元素为窗口中最大元素,则再取一次窗口中的最大值。这种算法避免了每次取k的值进行比较,只需比较新进入的数与原本窗口中最大的元素即可,减少了时间的复杂程度,代码如下:

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if k==1:
            return nums
        res = [max(nums[:k])]
        test = nums.copy()
        i = k
        for num in test:
            if len(nums) == k:
                break
            if nums.pop(0) != res[-1]:
                res.append(max(res[-1],test[i]))
            else:
                res.append(max(nums[:k]))
            i += 1
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值