欢迎光临
我们一直在努力

一天一道算法题(27):最小栈

155. 最小栈

文章目录

  • [155. 最小栈](https://leetcode.cn/problems/min-stack/)
    • ==思路==
      • – 辅助栈
      • – 不使用辅助栈,使用变量记录最小值
    • 结语

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

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int value) 将元素 value 推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 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.

思路

– 辅助栈

  • 既然我们要维护一个函数,且这个函数要求在O(1)时间复杂度取出最小值,那我们就有三个办法,一个是维护最小栈,一个是给栈排序,一个是记录最小值,这里我们直接pass给栈排序,因为这违背了栈的定义,且栈排序之后在取出顶部元素的时候会直接出错,辅助栈就是最小栈,栈顶维护最小值,方便直接取出,记录最小值是下一个方法

  • 时间复杂O(1),空间复杂度O(n)(我们就不把返回长度的库函数当做O(n),这里也可以使用一个变量记录长度,当入栈就++,出栈就–,这样时间复杂度就是O(1)了)

  • 代码演示

  • type MinStack struct {
    //记录所有元素的栈
    val []int
    //维护单调栈
    min []int
    }

    func Constructor() MinStack {
    //初始化,分配内存
    minStack := MinStack{
    val : []int{},
    min : []int{},
    }
    return minStack
    }

    func (this *MinStack) Push(value int) {
    //如果push进来元素,我们应该直接入val栈
    this.val = append(this.val, value)
    //如果入栈的元素比最小值还要小,那我们要入最小栈,否则就不入栈
    //另外一种情况是如果最小栈里面为空,那我们直接入栈
    if len(this.min) == 0 || value <= this.GetMin() {
    this.min = append(this.min, value)
    }
    }

    func (this *MinStack) Pop() {
    //删除val栈顶的元素的时候,我们要考虑栈顶元素是不是等于最小栈栈顶的元素,因为如果等于最小栈的栈顶元素,我们此时要弹出两个栈顶的元素
    if this.val[len(this.val)1] == this.min[len(this.min)1] {
    this.min = this.min[:len(this.min)1]
    }
    this.val = this.val[:len(this.val)1]
    }

    func (this *MinStack) Top() int {
    //直接返回val栈顶元素
    return this.val[len(this.val)1]
    }

    func (this *MinStack) GetMin() int {
    //返回最小栈的栈顶元素
    return this.min[len(this.min)1]
    }

– 不使用辅助栈,使用变量记录最小值

  • 我们可以使用min 变量记录最小值,把每一次要入栈的元素与当前的元素做差,如果差小于0,那我们就更换,否则就不更换,如果弹出栈顶的元素,我们判断当前栈顶元素与最小值的差,如果等于0,那我们就更新最小值,这里需要O(n)时间复杂度,依次遍历,如果是返回最小值,我们直接把该变量的值返回即可

  • 时间复杂度O(n),空间复杂度O(1)

  • 代码演示

  • type MinStack struct {
    //入栈每一个元素
    valStack []int
    //维护最小值
    min int
    }

    func Constructor() MinStack {
    return MinStack{
    valStack : []int{},
    //初始化为int32的最大值
    min : math.MaxInt32,
    }
    }

    func (this *MinStack) Push(value int) {
    //比较,如果新入栈的元素更小,更换值
    if value < this.GetMin() {
    this.min = value
    }

    this.valStack = append(this.valStack, value)
    }

    func (this *MinStack) Pop() {
    //如果弹出的元素就等于最小值,我们需要更新最小值,时间复杂度为O(n)
    if this.Top() == this.min {
    minTemp := math.MaxInt32
    //不遍历最后一位,给长度-1
    for i := 0; i < this.L()1; i++ {
    if this.valStack[i] < minTemp {
    minTemp = this.valStack[i]
    }
    }
    //更新
    this.min = minTemp
    }
    //弹出栈顶元素
    this.valStack = this.valStack[:this.L()1]
    }

    func (this *MinStack) Top() int {
    return this.valStack[len(this.valStack)1]
    }

    func (this *MinStack) GetMin() int {
    return this.min
    }

    func (this *MinStack) L() int {
    return len(this.valStack)
    }

    /**
    * Your MinStack object will be instantiated and called as such:
    * obj := Constructor();
    * obj.Push(value);
    * obj.Pop();
    * param_3 := obj.Top();
    * param_4 := obj.GetMin();
    */

结语

本文是 《算法题目解析系列》 的第 [27] 篇,本系列将持续更新,每篇都提供清晰的思路与编程语言实现。欢迎关注,第一时间获取更新。如果你有想看的题目,也可以在评论区留言告诉我。

赞(0)
未经允许不得转载:171主机测评 » 一天一道算法题(27):最小栈
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址