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

题目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]

思考

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质?你是否想成为一名资深开发人员,想开发别人做不了的高性能程序?你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? 那么C++就是你个人能力提升,职业之路进阶的不二之选。【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、针、标准库全部知识体系。2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署;2.吊打一切关于C++的笔试面试题;3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块基础篇本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、针、字符串等基本词法,循环、函数、类等基本句法等。进阶篇本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。提升篇:本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值