数据结构与算法笔记---栈---最小栈[1]

0.简介

本文章将介绍最小栈原理和实现。

1.最小栈

栈本身有push,pop操作,现在需要添加一个min操作,min操作就是求得栈中最小元素,要求时间复杂度是O(1)。

2.分析

其实求栈中最小值本身不是难题,这里难点在于时间复杂度是O(1),当找min值的时候,要求立刻就找到,这个就要追寻栈的一些本质算法。从数括号深度来看吧。

说有这么一段代码。

int fun()
{//作用域1
    int a;
    int b;

    {//作用域2
        int a;
        int b;
        {//作用域3
            int a;
            int b;
            a = a + b; //语句3
        }
        a = a + b;  //语句2
    }
    a = a + b;   //语句1
    return 0;
}

这段代码本身没什么意义,随意写的一段,我们要关注的是每个变量的作用域,我们很清楚的知道,语句3用的a、b变量一定是作用域3中的,因为距离语句3最近,我们可以认为是最近声明的变量在最上面。当退出作用域3来到作用域2的时候,语句2用的是作用域2中的a、b,这个过程就有些类似栈。这里所说的说的作用域的界限就是大括号。看下面的数字。


5
{ min = 5  //作用域1

   6  
   3
   2
    { min = 2  //作用域2

       8
       9
       7
       2
       1
        { min = 1 //作用域3

           6
           7
        }
    }
}

此时将大括号作用域上面增加了一个变量,叫做最小值,用这个最小值作为作用域界限,加入数字,从最上边往栈a中输入,当遇到第一个最小的值5,记录这个值,然后此时这个值就是目前栈中最小值,继续输入6、3、2,2比之前的5还要小,所以将2也存储下来,最后遇到比2还小的值1,那么把1也存贮,5、2、1这三个数字实际上就形成了三个不同的作用域,在作用域3的时候,栈中最小值是1,将7、6、1都出栈,此时作用域3消失,来到了作用域2,此时2是最小值,因为刚刚记录过了,我们将5、2、1这三个数一次存入了另一个栈b中了,所以将1出栈之后,栈顶就是2了,继续将栈a内容出栈,当出栈到2的时候,与栈b中记录的最小值一样,就相当于到了大括号,此时作用域2也消失,回到了作用域1。

看了上面一大段话,可能已经迷糊了,总结一下就是,原本的作用域是用大括号这个符号区分的,现在用当前最小值来当做作用域划分符号。用大括号区分的时候,因为大括号和数字不同,所以我们很轻松能知道什么是大括号,什么是数字,即便是都存储在一个栈里也能区分开。现在用最小值来划分作用域,因为最小值也是数字,和其余的值没有明显区别,所以我们将当前最小值存储在另外一个栈b中,也就是当前输入到栈a的值x,如果比栈b的top值y还要小,说明一个此时遇到新的作用域了,那么就将x存储栈b中,当从栈a出栈的时候,要比较出栈的值p是不是和栈b的top值q相等,是的话说明以p为界限的这个作用域已经从栈中彻底消失,退回到了上一个作用域了。总结也说了这么多。。。

那就再简化一下,栈可以保存并访问离当前状态最近的东西。

3.实现

class Solution {
public:
    stack<int>s;
    stack<int>m;
    void push(int value) {
        s.push(value);
        if(m.empty())
            m.push(value);
        if(m.top()>value)
            m.push(value);
    }
    void pop() {
        if(s.top() == m.top())
            m.pop();
        s.pop();
    }
    int top() {
        return s.top();
    }
    int min() {
        return m.top();
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值