python_lintcode_362. 滑动窗口的最大值

362. 滑动窗口的最大值

题目

给出一个可能包含重复的整数数组,和一个大小为 k 的滑动窗口, 从左到右在数组中滑动这个窗口,找到数组中每个窗口内的最大值。

样例
给出数组 [1,2,7,7,8], 滑动窗口大小为 k = 3. 返回 [7,7,8].

解释:

最开始,窗口的状态如下:

[|1, 2 ,7| ,7 , 8], 最大值为 7;

然后窗口向右移动一位:

[1, |2, 7, 7|, 8], 最大值为 7;

最后窗口再向右移动一位:

[1, 2, |7, 7, 8|], 最大值为 8.

思路

  • 牛客网的算法视频有讲解此类型题;
  • 方法一:每次对每个窗口遍历其中的k个数,选出最大值;
  • 方法二:使用双端队列,实现最大值的更新

双端队列

  • 定义双端队列(deque,全名double-endedqueue)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。

  • 操作:从右边加入,从左边弹出的操作

  • python中双端队列的操作函数;

    1. 先调用模块
      from collections import deque #首先从collections 模块中导入deque类

    2. 定义一个双端队列和操作

  • A=deque([]) #创建一个空的双队列
  • A.append(n) #从右边像队列中增加元素 ,n表示增加的元素
  • A.appendleft(n) #从左边像队列中增加元素,n表示增加的元素
  • A.clear() #清空队列
  • A.count(n) #在队列中统计元素的个数,n表示统计的元素
  • A.extend(n) #从右边扩展队列,n表示扩展的队列
  • A.extendleft(n) #从左边扩展队列,n表示扩展的队列
  • A.pop() #从队列的右边删除元素,并且返回删除值
  • A.popleft() #从队列的左边删除元素,并且返回删除值

方法二思路

  1. 定义一个双端队列qmax,存放数组中nums中的下标,初始qmax.append(0);定义一个存放每次窗口最大值res
  2. 取当前nums[1:]的的下标和nums值,为x,y,初始为1,nums[1]
  3. 判断qmax队尾存储的下标j,如果nums[j] > y,直接把下标x放进qmax队尾中;如果nums[j] <=y ,则一直从qmax的队尾弹出直到某个下标在qmax中对应的值大于y,此时把x放在qmax的队尾中.
  4. 执行一次步骤3,判断是否有过期的数(不属于当前k范围内的数)在qmax的队头中,有则popleft()删除该队头;然后存储当前窗口的最大值,即qmax的队头在res中。
  5. 使x = x+1 ;nums[y+1],执行步骤3和4直到达到nums的最后一个下标和值。

代码

from collections import deque
class Solution:
    """
    @param: nums: A list of integers
    @param: k: An integer
    @return: The maximum number inside the window at each moving
    """
    def maxSlidingWindow(self, nums, k):
        # write your code here
        #特殊情况,k=1,则每个都最大
        if k == 1:
            return nums
        #新建一个双端队列qmax,初始值为0
        #res存放每次移动的最大结果
        qmax = deque([])
        qmax.append(0)
        res = []

        for x,y in enumerate(nums[1:],1):
            """
            x,y表示当前的下标和nums值;
            判断qmax队尾存储的下标j,
            如果nums[j] > y,直接把下标x放进qmax队尾中;
            如果nums[j] <=y ,则一直从qmax的队尾弹出直到某个下标在qmax中对应的值大于y,
            此时把x放在qmax的队尾中.
            """
            if nums[qmax[-1]] <=y:
                for i in range(len(qmax)-1,-1,-1):
                    if nums[qmax[i]] > y:
                        break
                    else:
                        qmax.pop()         
            qmax.append(x) 
            #当qmax存在过期数据,即不在移动k范围内的,将其移除出双端队列
            if qmax[0] <= x-k:
                qmax.popleft()
            #将每次移动窗口的最大值存储到res中
            if x >=k-1:
                res.append(nums[qmax[0]])
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值