[剑指Offer] 59_队列的最大值

本文探讨了在数组和队列中寻找滑动窗口最大值的高效算法,提出了时间复杂度为O(n)的解决方案,并通过维护最大值队列确保O(1)的查询效率。

题目1:滑动窗口的最大值

给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。

例:

输入:[2, 3, 4, 2, 6, 2, 5, 1], 滑动窗口大小3
输出:[4, 4, 6, 6, 6, 5]


思路

  1. 遍历数组,每次计算滑动窗口中的最大值。
    1. 时间复杂度:O(mn)
    2. 空间复杂度:O(1)
  2. 遍历数组,按顺序保存当前位置窗口内的最大值,以及候选最大值。当新值进入时,从后向前判断是否大于候选最大值们,如果大于,则剔除这些候选,以新值替换,然后再剔除超出窗口的元素。
    1. 时间复杂度:O(n)
    2. 空间复杂度:O(m)

代码

思路2:时间复杂度:O(n),空间复杂度:O(m)

def max_in_sliding_window(array, window_width):
    """
    :param array: numbers
    :param window_width:sliding window size
    :return: all max number
    """
    if not array or window_width < 1:
        return None
    max_i = []
    res = []
    for i in range(len(array)):
        while max_i and array[i] >= array[max_i[-1]]:
            max_i.pop()
        max_i.append(i)
        while max_i and i - max_i[0] >= window_width:
            max_i.pop(0)
        if window_width - 1 <= i:
            res.append(array[max_i[0]])
    return res

题目2:队列的最大值

请定义一个队列并实现函数max得到队列里的最大值,要求函数max、push_back和
pop_front的时间复杂度都是O(1)。


思路

  1. 和题目1一样,在队列中维护一个保存最大值的队列,当pop和push操作的同时也对最大值队列进行维护。当弹出的时队列中的最大值时,也弹出最大值队列的头,当压入新值时,对最大值队列从后向前扫描剔除小于该值的元素。
    1. 时间复杂度:O(1)
    2. 空间复杂度:O(n)

代码

class Queue(object):

    def __init__(self):
        self.data = []
        self.max_data = []

    def pop(self):
        """
        pop out the head element
        :return: head element
        """
        if not self.data:
            raise Exception('Empty Queue Cannot Pop')
        if self.data[0] == self.max_data[0]:
            self.max_data.pop(0)
        return self.data.pop(0)

    def push(self, x):
        """
        push in the back
        :param x: element
        :return: None
        """
        self.data.append(x)
        while self.max_data and self.max_data[-1] < x:
            self.max_data.pop()
        self.max_data.append(x)
        return

    def max(self):
        """
        get the maximum element
        :return: max element
        """
        return self.max_data[0]

思考

利用队列先进先出的特点,可以免于考虑剔除最大值后,候补最大值不存在于队列的情况,大大减少了计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值