滑动窗口系列之求窗口中最大值问题

滑动窗口最大值

  • 问题: 给定一个数组,窗口长度为 k ,求每次窗口从左往右划过时每个窗口中的最大值

解决思路: 利用双端队列的性质----头部和尾部都能出和进;
队列中保存的是每个窗口内的最大值信息,关键在于窗口移动的过程中,如何更新其中的最大值信息。在每次窗口向右移动的过程中,都要判断两个信息:

  • 第一个,当前窗口的最大值是否需要更新;

解决方法: 判断当前值是否大于队列的尾部上的值,不成立的话就直接压入当前位置到队列尾部;如果成立,说明此时最大值需要更新了,那么把队列的尾部值弹出丢弃,直到当前值大于队列尾部的值或者队列已经弹空,然后再将当前值压入队列尾部;(队列尾部如果等于当前值的话,队列也需要弹出,因为队列中实际存放的是位置信息)

  • 第二个,队列中存放的最大值信息是否已经过期了,即该最大值是否还处在当前窗口内;

解决方法:判断是否过期,只要看队列中的值所对应的位置是否在当前窗口内即可。也就是说,因为压入时都是从尾部压入,所以头部的位置肯定是数组中最靠前的,所以只要判断队列头部值的位置是否已经不再窗口内,如果不在就弹出它,在就继续留着直到它过期为止。

至于最终结果的最大值,由于队列都是从尾部进,所以每个窗口的最大值一定放在头部位置,而且队列中的值一定都是在当前窗口内的,因为不在的话肯定就被弹出了。

时间复杂度: 由于数组中的每个数都只进出过队列一次,所以时间复杂度为O(N)。

具体实现:

  1. 准备一个双端队列 max_arr,存放的是当前窗口内最大值的下标;
  2. 从头开始遍历数组,假设当前遍历位置为 i ,如果 max_arr 不为空,并且 max_arr 中最后一个位置的值 小于等于 arr[i],那么 max_arr 一直从尾部弹出,直到不满足条件;此时,将当前 i 压入队列尾部;
  3. 压入当前位置后,判断 max_arr 中头部的位置值是否 在 窗口内,不在就弹出该位置;
  4. 继续判断 当前位置是否足够形成一个窗口(只在前 k 个位置时,不满足条件),满足形成窗口大小后,则将 max_arr 中头部的值放入结果数组中;
  5. 窗口向右移动,重复判断;

python 代码:

from collections import deque

# 窗口内的最大值
def max_value_window(arr, k):
    if len(arr) < k:
        return max(arr)
    res = []
    max_arr = deque()
    for i in range(len(arr)):
        while (len(max_arr) != 0 and arr[max_arr[-1]] <= arr[i] ): # 更新队列中的最大值
            max_arr.pop()
            
        max_arr.append(i) # 添加新值

        if max_arr[0] == i - k: # 队列中的值是否过期
            max_arr.popleft()
        if i >= k - 1:
            res.extend([arr[max_arr[0]]]) # 足够形成窗口时,窗口内最大值就是队列的头部

    return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值