ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

剑指offer笔记// 20·包含min函数的栈(R)

2020-02-03 17:42:57  阅读:256  来源: 互联网

标签:20 offer 元素 最小值 min 栈中 push stackLittle


题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

在该栈中,调用min、push及pop的时间复杂度都是O(1)。

关键词:栈

思路

链接:https://www.nowcoder.com/questionTerminal/4c776177d2c04c2494f2555c9fcc1e49?answerType=1&f=discussion
来源:牛客网

方法一:简单的双栈法

在返回栈中的min值时,如果仅仅使用一个辅助变量min,则其值可能因为min元素被出栈而失效,常规的做法是额外添加一个同步栈(min栈),以保存记录之前所有的min值,相当于是使用了n个辅助变量,所以空间复杂度是O(n)。

但是,仅仅使用一两个辅助变量就真的不能达到目的了??其实是可以的!当然,把两个栈的数据放在一个栈里的做法,显然不是这里要说的方法。我们考虑使用一种类似压缩的方法,来将数据栈和辅助栈合并成一个栈,因为经过分析可以发现,其实各个元素的值与最小值是有关联的,这之间存在着冗余的信息!

一个初步的优化是将min栈中因为没有新的min值入栈而产生的重复的min值舍弃掉,这一做法可以参考一叶浮尘的博客,但是在最坏情况下,它的辅助空间复杂度也是O(n),即每次入栈的值都是更小值

方法二:压缩还原法

我们发现其实最小值min它本身就是一种冗余信息。为什么呢?因为每个元素在数值上都包含了min值,举个例子,假设入栈序列为:4、5、6、3、2、1,那么各轮次对应的min值就是:4、4、4、3、2、1,发现有:
4=4+0,5=4+1,6=4+2,3=4+(-1),2=3+(-1),1=2+(-1);各个元素在数值上已经包含了在它之前的最小值的值;
那么,我们是不是只要在数据栈中存储0、1、2、-1、-1、-1,然后再使用一个辅助变量min=1就可以了呢?
这样,根据单个辅助变量和栈中存储的值就能够推理出top值和min值了,具体规则如下:

入栈:

压缩:将要入栈的元素value减去当前最小值min,得到一个差值diff,只存储该差值;
更新:如果入栈的元素value比当前最小值min小,则要更新最小值:min=value;
初始:第一次入栈比较特殊,因为此时的min变量并没有值,所以令:min=value;

出栈:

更新:如果栈中存储的差值diff是负数,说明出栈的元素是当前最小值min,需要把min值更新为上一个最小值min = min - diff,否则,出栈的元素不是最小值,则不对min变量做任何操作;
还原:如果栈中存储的差值diff是正数,说明 top = min + diff,否则,说明top元素本身是最小值 top = min;

简单来说,就是要实现push、pop、getmin、top功能
样例:

MinStack minStack = new MinStack();
minStack.push(-1);
minStack.push(3);
minStack.push(-4);
minStack.getMin();   --> Returns -4.
minStack.pop();
minStack.top();      --> Returns 3.
minStack.getMin();   --> Returns -1.

思路:

push(x)–将元素x插入栈中
pop()–移除栈顶元素
top()–得到栈顶元素
getMin()–得到栈中最小元素

使用两个栈。
“stackTotal”:用来存所有的元素,
“stackLittle”:另一个用来存加入新的元素后当前stackTotal中对应的最小值。

两个栈中的元素数量始终保持一致,当新的元素小于“stackLittle”栈顶元素时,“stackLittle”像栈顶push新来的元素,否则,“stackLittle”向栈顶加入原栈顶元素。

在这里插入图片描述

代码实现

import java.util.Stack;
 
public class Solution {

	//(顺序)定义两个栈,
    Stack<Integer> stackTotal = new Stack<Integer>();
    Stack<Integer> stackLittle = new Stack<Integer>();
 
 	//(顺序)压栈
    public void push(int node) {
    	//(顺序)随stackTotal压栈,直接压栈即可
        stackTotal.push(node);
        //(顺序)stackLittle压栈,需要比较大小
        //(选择)如果是第一个元素,需要赋初值,直接将node的值赋给min
        if(stackLittle.empty()){
            stackLittle.push(node);
        }else{
            if(node <= stackLittle.peek()){
                stackLittle.push(node);
            }else{
                stackLittle.push(stackLittle.peek());
            }
        }
    }
 	//(顺序)移除栈顶元素
    public void pop() {
        stackTotal.pop();
        stackLittle.pop();
    }
 	
 	//(顺序)获得栈顶元素
    public int top() {
        return stackTotal.peek();
    }
 
 	//(顺序)获得最小元素
    public int min() {
        return stackLittle.peek();
    }
}

总结

时间复杂度的计算并不是计算程序具体运行的时间,而是算法执行语句的次数。

计算方法
①选取相对增长最高的项
②最高项系数是都化为1
③若是常数的话用O(1)表示
如f(n)=2*n3+2n+100则O(n)=n^3。

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。

  • 定义栈的标准方式:
    Stack stackTotal = new Stack();

  • peek() 方法用于查找在此堆栈顶部的对象,无需从堆栈中取出。

  • 句式翻译:
    获得stack的栈顶元素:return stack.peek()

peek:方法调用返回在这个堆栈的顶部的对象。
移除stack栈顶元素:stack.pop()

时光猎人688 发布了31 篇原创文章 · 获赞 4 · 访问量 993 私信 关注

标签:20,offer,元素,最小值,min,栈中,push,stackLittle
来源: https://blog.csdn.net/qq_37177765/article/details/104156699

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有