设计一个栈,除pop与push方法,还支持min方法,可返回栈元素中的最小值。
push,pop和min三个方法的时间复杂度必须为O(1)
要保证min的时间复杂度为O(1), 那就不能每次通过遍历整个栈来获取最小值。假设这个栈初始为5:
5; 最小值为5; 压入7,栈变为
7,5;最小值为5; 压入3,栈变为
3,7,5; 最小值为3
这时弹出3,栈变为
7,5; 最小值为5; 弹出7, 栈变为
5; 最小值为5;
注意在7,5这个状态时,最小值都是5. 也就是说,如果我们能标记出栈的每个状态,那么可以直接取出最小值。可以用一个栈来保存最小值。
stack类的peek()方法,查看栈顶对象而不移除它
- /**
- * 思路:每个结点记录当前最小值。
- * 缺点:当栈很大时,每个元素都要记录 min,就会浪费大量空间。
- */
- public class StackWithMin extends Stack<NodeWithMin>{
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- }
- public void push(int value){
- int newMin=Math. min(value , min());
- super.push( new NodeWithMin( value, newMin));
- }
- public int min(){
- if( this.isEmpty())
- return Integer. MAX_VALUE;
- else
- return peek(). min;
- }
- }
- class NodeWithMin{
- public int value;
- public int min;
- public NodeWithMin( int value, int min){
- this. value= value;
- this. min= min;
- }
- }
对于栈,实现其min方法很简单,就是每次push一个值的时候,对minValue进行维护:
if(value < minVlaue){
minValue = value;
}
- 1
- 2
- 3
- 1
- 2
- 3
每次调用min() 时直接返回minValue即可。但是,如果pop走的是minValue则需要遍历剩下的元素求最小值。所以这样无法满足O(1)的要求,我们需要额外的空间保存栈的每一个状态下的最小值。
正如上面陈述的,只要当push的值小于minValue时和pop的值等于minValue时才需要进行额外的操作,用额外的一个栈 stackOfMin来记录最小值的情况。当push的值小于minValue时,stackOfMin push新的最小值;pop的值等于minValue时,stackOfMin也相应地pop就行。
代码
package test1; import java.util.Stack; public class StackWithMin extends Stack<Integer>{ private Stack<Integer> stackOfMin; public StackWithMin() {
//存放最小值的栈stackOfMin = new Stack<>(); } public int min() { if(stackOfMin.isEmpty()){ return Integer.MAX_VALUE; }else { return stackOfMin.peek(); } } @Override public Integer push(Integer item) { if(item < min()){ stackOfMin.push(item);
//调用自身Stack的Push方法,而不是StackWithMin2的方法(sMin是Stack类)} return super.push(item); } @Override public synchronized Integer pop() { if(this.peek() == min()){ stackOfMin.pop(); } return super.pop(); } public static void main(String[] args) { StackWithMin stackWithMin = new StackWithMin(); stackWithMin.push(19); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.push(15); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.push(17); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.pop(); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.pop(); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.push(30); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.push(1); System.out.println("The min is: "+stackWithMin.min()); stackWithMin.push(4); System.out.println("The min is: "+stackWithMin.min()); } }
The min is: 19
The min is: 15
The min is: 15
The min is: 15
The min is: 19
The min is: 19
The min is: 1
The min is: 1