offer30 offer59_II 栈和队列的最小最大值(线性复杂度)(简单)

offer_30 包含min函数的栈   Offer 59 - II. 队列的最大值

本文对上述两个题目做适当延申,如何模拟求队列最小值最大值

重点:要实现min/max 的时间复杂度为O(1)    故增加一个辅助列表

两个任务各个函数复杂度: 时间复杂度:O(1)    空间复杂度:O(n) 

分析举例:(延申的代码没实现 各实现了一个)

                # 求队列最大值的话 则
                q1 = [-2 0 -3]  q2 = [-2 0]
                     q1 = [5 8 6 3 7 4] 5是队头  q2 = [8 7 4]  最大值取第一个值   递减列表
                     * 当新进来的值比较大时  需要将它前边的比它小值都pop出去  若新进来的值较小 直接加入

                # 【延申】 求队列最小值的话 则
                    q1 = [5 8 6 3 7 4] 5是队头  q2 = [3 4]    最小值取第一个值    递增列表
                    * 当新来的值比较小时  需要将它前边的比它大的值都pop出去  若新来的值比较大 直接加入

              # 求栈最小值
                    s1 = [5 8 6 3 7 4] 4是栈顶  s2 = [5 3]  递减列表

              #【延申】 求栈最大值的话 则
                  s1 = [5 8 6 3 7 4] 4是栈顶  s2 = [5 8]  递增列表

队列的最小最大值(线性时间复杂度)

'''
    题目:请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
    思路:
        ⭐ 还有由列表来模拟
        ⭐ 函数max_value如果需实现时间复杂度为O(1) 则同样需要一个有序队列 来记录顺序的较大值  此处我们使用递减列表
            例:
                # 求队列最大值的话 则
                q1 = [-2 0 -3]  q2 = [-2 0]
                     q1 = [5 8 6 3 7 4] 5是队头  q2 = [8 7 4]  最大值取第一个值   递减列表
                     * 当新进来的值比较大时  需要将它前边的比它小值都pop出去  若新进来的值较小 直接加入

                # 【延申】 求队列最小值的话 则
                    q1 = [5 8 6 3 7 4] 5是队头  q2 = [3 4]    最小值取第一个值    递增列表
                    * 当新来的值比较小时  需要将它前边的比它大的值都pop出去  若新来的值比较大 直接加入
    各个函数的复杂度: 时间复杂度O(1)  空间复杂度O(n)
'''

class MaxQueue(object):

    def __init__(self):
        self.q1, self.q2 = [], []

    def max_value(self):
        """
        :rtype: int
        """
        if not self.q2:
            return -1
        else:
            return self.q2[0]
    # 要保证 q2中的元素记录的是递减序列  如  [5 8 6 1 7] 记录的是 [8 7]  这就要求当新进来的值比较大时  需要将它前边的比它小值都pop出去  若新进来的值较小 直接加入
    def push_back(self, value):
        """
        :type value: int
        :rtype: None
        """
        if not value:
            return
        self.q1.append(value)

        # 列表不为空  且 新元素大于q2中最后一个元素
        while self.q2 and self.q2[-1] < value:
            self.q2.pop()
        self.q2.append(value)

    def pop_front(self):
        """
        :rtype: int
        """
        if not self.q1:
            return -1
        else:
            temp = self.q1.pop(0)
            if self.q2 and temp == self.q2[0]:
                self.q2.pop(0)
            return temp


obj = MaxQueue()
obj.push_back(1)
obj.push_back(2)
print(obj.max_value())
print(obj.pop_front())
print(obj.max_value())

栈的最小最大值(线性时间复杂度)


'''
    题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
    思路:
        ⭐ 栈使用python中的 列表(pop ) 来模拟
        ⭐ 其中push和pop的时间复杂度都是O(1)  如果直接调用list中的min 则其时间复杂度为O(n)  所以目前要考虑如何设计使得min函数的时间复杂度为O(1)
        ⭐ 最简单的想法是增加一个变量 专门用来记录栈中的最小值   但是如果该值被pop出去 则次小值还得再找,所以应该记录一个有序列表(我们记录为一个辅助栈 一个降序列表)
        例:
            # 求栈最小值
            s1 = [5 8 6 3 7 4] 4是栈顶  s2 = [5 3]  递减列表

            #【延申】 求栈最大值的话 则
            s1 = [5 8 6 3 7 4] 4是栈顶  s2 = [5 8]  递增列表
    各个函数的复杂度: 时间复杂度O(1)  空间复杂度O(n)
'''
class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.s1 = []
        self.s2 = []

    def push(self, x):
        """
        :type x: int
        :rtype: None
        """
        self.s1.append(x)
        if not self.s2 or self.s2[-1] >= x:
            self.s2.append(x)

    def pop(self):
        """
        :rtype: None
        """
        temp = self.s1.pop(-1)
        if temp == self.s2[-1]:
            self.s2.pop()
        return temp

    def top(self):
        """
        :rtype: int
        """
        if self.s1:
            return self.s1[-1]
        else:
            return []

    def min(self):
        """
        :rtype: int
        """
        if self.s1:
            return self.s2[-1]
        else:
            return []
obj = MinStack()
obj.push(-2)
obj.push(0)
obj.push(-3)
print(obj.pop())
param_3 = obj.top()
param_4 = obj.min()

print(param_3)
print(param_4)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值