• 打败算法 —— 最小栈


    本文参考

    出自LeetCode上的题库 —— 最小栈,根据官方的解法需要额外建立一个辅助栈,本文提出不需要额外空间的解法

    https://leetcode-cn.com/problems/min-stack/

    最小栈问题

    设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈

    示例1:
    输入:["MinStack","push","push","push","getMin","pop","top","getMin"]
               [ [], [-2], [0], [-3], [], [], [], [] ]
    输出:[ null, null, null, null, -3, null, 0, -2 ]
    解释:MinStack minStack = new MinStack();
               minStack.push(-2);
               minStack.push(0);
               minStack.push(-3);
               minStack.getMin(); --> 返回 -3.
               minStack.pop();
               minStack.top(); --> 返回 0.
               minStack.getMin(); --> 返回 -2.

    解题思路

    一般的栈结构在进行pop操作时,要求将弹出的元素返回,但是本题保证了pop、top 和 getMin 操作总是在非空栈上调用,我们甚至都不需要在top和getMin函数中判断当前的栈是否为空,所以可以很简洁地设计这些基本的栈操作

    向栈中压入元素时,官方题解额外用一个辅助栈存储此时的最小值,尽管这种解法非常容易理解,但是除栈本身外,带来了$O(n)$的空间复杂度。因此,为了将空间复杂度降到$O(1)$常数级别,我们仅在栈中存储与当前最小值相比的差值。理解的难度主要在于如何对差值进行处理,例如,在调用top时,如何将差值还原回本身的数值;在调用pop时,如何利用差值更新当前的最小值

    差值解法

    class MinStack:

      def __init__(self):
        # 模拟栈 

        self.stack = list()
        # 记录最小值 

        self.min_value = -1
        # 栈元素个数计数 

        self.cnt = 0

      # 压栈 

      def push(self, val: int) -> None:
        # 第一个元素 

        if not self.cnt:
          self.stack.append(val)
          self.min_value = val
        else:
          # 栈内存储差值 

          sub = val - self.min_value
          self.stack.append(sub)
          self.min_value = self.min_value if sub > 0 else val
        self.cnt += 1

      # 出栈 

      def pop(self) -> None:
        self.cnt -= 1
        sub = self.stack.pop()
        # 差值 
    < 0 更新最小值
        if sub < 0:
          self.min_value -= sub

      # 栈顶 

      def top(self) -> int:
        sub = self.stack[-1]
        if self.cnt > 1:
          # 根据差值还原回原来的数值 

          return self.min_value if sub < 0 else sub + self.min_value
        else:
          # 栈中只有 1 个元素时直接返回 

          return sub

      # 最小值 

      def get_min(self) -> int:
        return self.min_value

  • 相关阅读:
    730. 统计不同回文子序列(难,答案也难)
    354. 俄罗斯套娃信封问题
    Springboot中使用自定义validator
    graphQL官方网站
    在springboot中使用jdbcTemplate(4)和okhttp3
    springboot过滤器和拦截器(二)
    分布式事务转载
    graphQLjava实战(四)graphiql实现分页
    Spring Boot 如何实现Bean的刷新(转)
    SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源)转载
  • 原文地址:https://www.cnblogs.com/kuluo/p/15986691.html
Copyright © 2020-2023  润新知