问题描述:
实现一个栈,带有出栈(pop),入栈(push),取最小元素(getMin)三个方法。要保证这三个方法的时间复杂度都是O(1)。
问题分析:
假设存储元素的栈为ms栈;
主要的难点在于获取栈最小元素getMin()要保证其时间复杂度为O(1);
而且由于存在push()和pop()操作,栈中最小元素currMin随时可能会因为入栈元和弹出操作而发生动态变化,因此需要一种机制,能够时刻记录当前栈的最小元素;
这里,可以考虑用一个辅助栈aux,当ms栈的第一个元素入栈时,aux将第一个元素的索引0入栈;
那么后续如何来保证aux的栈顶元素实时记录着ms栈的最小元素的索引呢?
当入栈操作时,如果入栈元素小于当前栈中最小元素(aux栈顶元素所对应的元素),更新当前最小元素,并将新的最小元素的索引(也即是top值)入辅助栈;
当出栈操作时,如果出栈元素等于当前栈中最小元素,先将aux栈顶元素弹出,在更新当前最小元素;
如此操作可保证aux的栈顶元素实时记录着ms栈当前元素的最小值。
实现:
package agother;
import java.util.ArrayList;
import java.util.Stack;
public class MinStack {
private ArrayList<Integer> ms = new ArrayList<Integer>();//栈元素的存储借助ArrayList
private Stack<Integer> aux = new Stack<Integer>();//辅助的普通栈
private int currMin = Integer.MAX_VALUE;//当前最小值
private int top = -1;//栈顶指针
public void push(int ele){
ms.add(ele);
top++;
if (ele < currMin) {//如果入栈元素小于当前栈中最小与元素,更新当前最小元素,并将新的最小元素的位置(也即是top值)入辅助栈
currMin = ele;
aux.push(top);
}
}
public Integer pop(){
if (top<0) {return null;}
Integer ele = ms.remove(top);
top--;
if (ele == currMin) {//如果出栈元素等于当前栈中最小元素,更新当前最小元素为次小元素,并弹出aux栈顶元素。
aux.pop();
currMin = ms.get(aux.peek());
}
return ele;
}
/*
* 实际上,辅助栈的栈顶元素始终记录的是ms栈中最小元素的索引值
* 即是是在ms压栈或者出栈的过程中,通过调整,任然保持着这一事实
* 因此getMin()方法总能以O(1)的时间复杂度正确找到ms栈的最小元素
* */
public Integer getMin(){
if (aux.isEmpty()) {
return null;
}else {
return currMin;//或者返回ms.get(aux.peek())
}
}
public int size(){
return top+1;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
MinStack ms = new MinStack();
ms.push(10);
ms.push(3);
ms.push(5);
ms.push(15);
ms.push(2);
ms.push(8);
// System.out.println(ms.size());
// System.out.println(ms.getMin());
// System.out.println(ms.pop());
// System.out.println(ms.pop());
// System.out.println(ms.pop());
// System.out.println(ms.pop());
// System.out.println(ms.pop());
System.out.println(ms.getMin());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
转载请注明原文地址:http://www.cnblogs.com/qcblog/p/7695988.html