239. 滑动窗口最大值

239. 滑动窗口最大值

给定一个数组 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

2.暴力

遍历数组
时间复杂度和空间复杂度都比较高

class Solution:
    def maxSlidingWindow(self, nums: 'List[int]', k: 'int') -> 'List[int]':
        n = len(nums)
        if n == 0 or  k == 0:  
            return []   
        if k == 1: return nums
        return [max(nums[i:i + k]) for i in range(n - k + 1)]

3.动态规划

把数组分成长度为k(滑动窗口的长度)的块
用left记录从左到右遍历每个块的当前最大值
用right记录从右到左遍历每个块的当前最大值
则滑动窗口[i:j]的最大值在对应位置的left[j] 或者right[i]

class Solution:
    def maxSlidingWindow(self, nums: 'List[int]', k: 'int') -> 'List[int]':
        n = len(nums)
        if n == 0 or  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):
            if i % k == 0:
                left[i] = nums[i]
            else:
                left[i] = max(left[i - 1], nums[i])
            j = n - i - 1
            if (j + 1) % k == 0:
                right[j] = nums[j]
            else:
                right[j] = max(right[j + 1], nums[j])
        
        result = []
        for i in range(n - k + 1):
            result.append(max(left[i + k - 1], right[i]))          
        return result

4.双端队列

collections 是 python 内建的一个集合模块,里面封装了许多集合类,其中队列相关的集合只有一个:deque。
deque 是双边队列(double-ended queue),具有队列和栈的性质,在 list 的基础上增加了移动、旋转和增删等。
https://blog.csdn.net/happyrocking/article/details/80058623

在这里插入图片描述
1.用队列记录最大值的位置(有点抽象不好理解,特别是if和while的判断语句,知其然不知其所以然)

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        if n == 0 or  k == 0:  
            return []   
        if k == 1: return nums

        deque = collections.deque()
        result = []
        for i in range(len(nums)):
            #i表示滑动窗口的最后一位,判断队列是否超出窗口
            if deque and deque[0] <= i - k: 
                a=deque.popleft()
                #print("a=",a)
     #新进来的元素需要与窗口中元素比较,弹出小于新元素的所有元素
            while deque and nums[i] > nums[deque[-1]]: 
                b=deque.pop()
                #print("b=",b)
            deque.append(i)
            #print("d=",deque)            
            if i >= k - 1:
                result.append(nums[deque[0]])
                #print(result)
        return result

2.用队列直接记录元素

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if not nums or k == 0:
            return []
        cur_max = max(nums[ : k])
        res = [cur_max]
        size = len(nums)
        for i in range(1, size - k + 1):
            # 如果最大值是移走的元素,那就重新计算最大值。
            if nums[i - 1] == cur_max:
                cur_max = max(nums[i : i + k])
            # 表明最大值就在当前的区域中,需和新加入的元素相比较。
            else:
                cur_max = max(cur_max, nums[i + k -1])
            res.append(cur_max)
        return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值