博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计一个有 getMin功能的栈
阅读量:3740 次
发布时间:2019-05-22

本文共 3936 字,大约阅读时间需要 13 分钟。

        该题目来自《程序员代码面试指南》,在理解其实现原理的基础上,将Java实现改用C++实现。

题目

        实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。

要求

  • pop、push、getMin操作的时间复杂度都是O(1) 。
  • 设计的栈类型可以使用现成的栈结构 。
难度
        *
解答
        在设计上我们使用两个栈,一个栈用来保存当前栈的元素,其功能和一个正常的栈没有区别,这个栈即为stackData,另一栈用于保存每一步的最小值,这个栈记为stackMin。具体的实现方式有两种。
第一种实现方案为:
  • 压入数据规则
        假设当前数据为newNum,先将其压入stackData。然后判断stackMin是否为空:
    • 如果为空,则newNum也压入stackMin
    • 如果不为空,则比较newNum和stackMin中栈顶的元素的大小:
      • 如果newNum更小或两者相等,则newNum也压入stackMin。
      • 如果stackMin栈顶元素更小,则stackMin不压入任何内容。
  • 弹出规则
        先在stackData中弹出栈顶元素,记为value。然后比较当前stackMin的栈顶元素和value哪一个更小。通过上面的压入规则可知,stackMin中存在的元素是从栈底到栈顶逐渐变小的,stackMin栈顶的元素既是stackData栈中最小的元素,也是stackMin栈中最小的元素。
        因此,当value等于stackMin栈顶元素时,stackMin栈也弹出栈顶元素。当stackMin栈顶元素小于value值时,stackMin不弹出栈顶元素。最后返回value。可以看出,压入规则和弹出规则是对应的。
  •  查询当前栈中的最小值操作
        由上文可以,stackMin栈顶元素始终是当前stackData栈的最小元素。因此查询stackMin栈顶元素即可知道当前栈中的最小元素。
public class MinStack1{    private Stack
stackData; private Stack
stackMin; public MinStack1(){ stackData = new Stack
(); stackMin = new Stack
(); } public void push(int newNum){ if (stackMin.isEmpty()) { stackMin.push(newNum); }else if (newNum <= getMin()) { stackMin.push(newNum); } stackData.push(newNum); } public int pop(){ if (stackData.isEmpty()) { throw new RuntimeException("Your stack is empty!"); } int value = stackData.pop(); if (value == getMin()) { stackMin.pop(); } return value; } public int getMin() { if (stackMin.isEmpty()) { throw new RuntimeException("Your stack is empty!"); } return stackMin.peek(); } }
class MyStack1 //C++实现{private:	stack
stackData; stack
stackMin;public: MyStack1(){} void push1(int numNum); int pop1(); int getmin();};void MyStack1::push1(int newNum){ if(stackMin.empty()) stackMin.push(newNum); else if(newNum <= getmin()) stackMin.push(newNum); stackData.push(newNum);}int MyStack1::pop1(){ if(stackData.empty()) { cout<<"your stack is empty."; return -1; } int value = stackData.top(); //由于c++中pop函数的返回类型为void,因此不能采用Java中的描述实现。 stackData.pop(); if(value == getmin()) stackMin.pop(); return value;}int MyStack1::getmin(){ if(stackMin.empty()) { cout<<"your stack is empty"; return -1; } return stackMin.top();}
class MinStack {  //LeetCode下该问题的优质回答。结合上面正确的逻辑,这个代码实现地非常简洁清晰。private:    stack
s1; stack
s2;public: void push(int x) { s1.push(x); if (s2.empty() || x <= getMin()) s2.push(x); } void pop() { if (s1.top() == getMin()) s2.pop(); s1.pop(); } int top() { return s1.top(); } int getMin() { return s2.top(); }};
第二种设计方案的思路这里简单的介绍一下:
        假设当前数据为newNum,先将其压入stackData。然后判断stackMin是否为空:
    • 如果为空,则newNum也压入stackMin。如果不为空,则比较newNum和stackMin中栈顶的元素的大小:
      • 如果newNum更小或两者相等,则newNum也压入stackMin中。
      •   如果stackMin栈顶元素更小,则把stackMin栈顶元素重复地压入stackMin中。
              
public class MinStack2 {    private Stack
stackData; private Stack
stackMin; public MinStack(){ stackData = new Stack
(); stackMin = new Stack
(); } public void push(int newNum){ if (stackMin.isEmpty()) { stackMin.push(newNum); } else if (newNum <= getMin()) { stackMin.push(newNum); }else { stackMin.push(getMin()); } stackData.push(newNum); } public int pop(){ if (stackData.isEmpty()) { throw new RuntimeException("Your stack is empty!"); } int value = stackData.pop(); stackMin.pop(); return value; } public int getMin(){ if (stackMin.isEmpty()) { throw new RuntimeException("Your stack is empty!"); } return stackMin.peek(); }}
       
        方案一和方案二都是使用stackMin栈保存着stackData每一步的最小值。共同点是所有操作的时间复杂度为O(1),空间复杂度为O(n)。
参考链接     
学习书籍   《程序员代码面试指南》
 

你可能感兴趣的文章
实验七 香农编码
查看>>
使用react脚手架创建react项目时发生错误
查看>>
关于setState是异步与同步的
查看>>
20. 有效的括号---js解法
查看>>
56. 合并区间---js解法
查看>>
5. 最长回文子串---js解法
查看>>
USACO 2007 Open Gold/acwing2240:餐饮 (拆点+最大流)‘三分图匹配’
查看>>
那些年你不知道的C++STL进制转换函数
查看>>
区间和并问题 思路加模板整理(校门外的树)
查看>>
C++中next_permutation函数的使用方法、原理及手动实现
查看>>
网络流常用小技巧之 拆点
查看>>
掌握01分数规划 思想+应用模型总结
查看>>
最大权闭合子图
查看>>
最大密度子图
查看>>
最小权点覆盖集 与 最大权独立集
查看>>
POJ 2125 Destroying The Graph && Acwing 2325. 有向图破坏(拆点+最小权点覆盖集)
查看>>
Acwing 2326:王者之剑(网格图之网络流 最大权独立集)
查看>>
[网络流24题]洛谷P1251 / Acwing 2184: 餐巾计划问题(建图+拆点+最小费用最大流)
查看>>
NOI2008 & Acwing 969:志愿者招募(特殊的建图 与 无源汇|上下界|最小费用|可行流)
查看>>
计算几何基础知识整理大全 代码模板与证明过程 (直线、向量、多边形、三维计算几何、凸包、半平面交、最小圆覆盖)
查看>>