实现一个栈(元素遵守先入后出顺序),能够通过 min 方法在 O(1)时间内获取栈中的最小元素。同时,栈的基本操作:入栈(Push)、出栈(Pop),也是在O(1)时间内完成的

实现一个栈(元素遵守先入后出顺序),能够通过 min 方法在 O(1)时间内获取栈中的最小元素。同时,栈的基本操作:入栈(Push)、出栈(Pop),也是在O(1)时间内完成的。

此问题可分析为:

方案一:

建立两个栈,一个用来存放插入的数据datastack,一个用来存放最小的数据minstack;当最小栈不为空时,在datastack中插入一个数据,先用一变量tmp来存放minstack栈顶元素,将插入数据与tmp比较,若插入数据小将插入数据拷贝一份push进minstack栈内,若tmp小再压入minstack栈内,依次重复。

方案二:

只用建一个栈,但每push进一个元素,先于原来较小元素比较,若原来小,将原来数据拷贝一份入栈,接着将刚要入栈的的元素入栈,也就是说,每次要push一个元素进去,首先得判断,先入的是较小元素或其拷贝,然后是要入栈的元素。

 数据结构实现:

#include <iostream>  
#include<stdlib.h>
using namespace std;   
#include <stack>   
template <class T>  
class retmin  
{  
public :  
     void pushmin(const T& x)  
    {  
         _num.push (x);  
          if(!_min.empty ())  
         {  
             T tmp = _min.top ();  
              if( x < tmp)  
             {  
                 _min.push (x);  
             }  
              else  
                 _min.push (tmp);  
         }  
          else  
             _min.push (x);  
           
    }  
     void popmin()  
    {  
         _num.pop ();  
         _min.pop ();  
    }  
  
    T Retmin()  
    {  
          return _min.top ();  
    }  
private :  
    stack<T> _num;  
       stack<T> _min;  
};  
  
  
void Test9()  
{  
    retmin< int> r1;  
    r1.pushmin (5);  
    r1.pushmin (4);  
    r1.pushmin (3);  
    r1.pushmin (6);  
    r1.pushmin (1); 
	r1.pushmin (5);  
    r1.pushmin (4);  
    r1.pushmin (2);  
    r1.pushmin (6);  
    r1.pushmin (1); 
    cout<<r1.Retmin ()<<endl;  
}  
  
int main()  
{  
    Test9(); 
	system("pause");
     return 0;  
}  

java实现

思路1:添加一个成员变量总是保存当前栈中最小的元素。该思路的实现代码大致是这样的:

复制代码
public class MinStack {
    
    private LinkedList<Integer> stack;
    private int min;// save minimum ele of stack
    
    public int pop(){
        //check pop minimum ele?
    }
    public void push(int ele){
        //check push minimum ele?
    }
    public int getMin(){
        return min;
    }
}
复制代码

 

这里就会存在一个问题:保存最小元素的 min 属性 与 栈中的最小元素不一致。

比如:当从栈中 pop 最小元素时,那 min 属性就要 保存 次最小元素了。那如何 找到次最小元素,然后赋值给 min 呢?

 因此,问题的关键就是:当只使用一个 min 属性时,如何保证 min 属性 总是 保存的是当前栈中最小的元素?---即: min 代表的最小元素 要与 栈中的最小元素保存一致。一种方式是当pop出最小元素之后,再遍历栈找出次最小的元素,并将之赋值给 min 。但是,由于遍历使得时间复杂度不再是O(1)

 

思路2:

使用一个辅助栈。此方法能够实现在O(1)时间内获取栈中最小的元素,但是缺点是空间复杂度为O(N)

现在有两个栈:一个是保存元素的数据栈,另一个是辅助栈,辅助栈的栈顶总是 当前数据栈中最小的元素。当Push元素时,首先将该元素Push到数据栈,然后再将该元素与辅助栈的栈顶元素比较:如果该元素比辅助栈的栈顶元素小,则将该元素Push到辅助栈中;否则将辅助栈的栈顶元素再Push到辅助栈中。

比如,现在要Push的元素顺序如下:3,4,2,5....   在数据栈 和 辅助栈中保存的元素如下:

 

三,代码实现

代码中使用了 java.util.LinkedList 类作为 栈的实现。

复制代码
import java.util.LinkedList;

public class MinStack {
    
    private LinkedList<Integer> dataStack;
    private LinkedList<Integer> minStack;
    
    public MinStack() {
        dataStack = new LinkedList<Integer>();
        minStack = new LinkedList<Integer>();
    }
    
    //base operation
    public void push(int ele)
    {
        dataStack.push(ele);
        if(minStack.size() == 0 || ele < minStack.peek())
            minStack.push(ele);
        else
            minStack.push(minStack.peek());
    }
    
    public Integer pop(){
        if(dataStack.isEmpty())
            return null;
        
        assert dataStack.isEmpty() == false && minStack.isEmpty() == false;
        int ele = dataStack.pop();
        minStack.pop();
        return ele;
    }
    
    public Integer min(){
        if(minStack.isEmpty())
            return null;
        return minStack.peek();
    }
    
    //hapjin test
    public static void main(String[] args) {
        MinStack stack = new MinStack();
        
        int[] eles = {3,4,2,5};
        for (int i : eles) {
            stack.push(i);
        }
        System.out.println(stack.min());//2
        System.out.println(stack.pop());//5
        System.out.println(stack.pop());//2
        System.out.println(stack.min());//3
        stack.push(1);
        System.out.println(stack.min());
    }
}
复制代码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值