堆栈变体以及栈和队列的相互实现

前面讲到了如何用数组以及链表实现一个基本的堆栈和队列,这篇文章介绍如何实现一个可以在O(1)时间复杂度下得到最小元素的堆栈,以及用堆栈实现一个队列,用队列实现一个堆栈。

1,实现一个可以得到最小元素的堆栈, 要求pop(),push(),getMin()的时间复杂度都为O(1).

如果我们按照普通的思路,类中有两个成员变量,value和minValue,当pop一个元素后,我们就需要更新minValue, 从而要遍历堆栈里剩余的元素,时间复杂度为O(n),假设堆栈中有n个元素,因此这个方法不符合题意。

我们想到用每个元素都记录当前的最小元素,当push一个新的元素进来,这个新的元素连同最小元素都被记录在堆栈中,我们先不考虑pop,实现代码如下:
public class StackWithMin extends Stack<EleWithMin>{
	public void push(int val) {
		int min = Math.min(val, min());
		super.push(new EleWithMin(val, min));
	}

	public int pop() {
		/* 
		after we pop a element,
		how can we update the min in
		stack if this is the minimum value
		*/
		super.pop().value;

	}
	public int min(){
		if(this.isEmpty()){
			return Integer.MAX_VALUE;
		} else {
			return peek().min;
		}
	}
}

class EleWithMin {
	public int value;
	public int min;

	public EleWithMin(int value, int min) {
		this.value = value;
		this.min = min;
	}
}


他的确可以在O(1)的时间内得到最小元素,但是pop后,我们仍然需要更新最小值,时间复杂度大于O(n)。并且浪费空间,因为每个元素都要记录一个当前的最小元素。我们换另一种方法,用另外一个堆栈来记录最小元素。代码如下:
import java.util.Stack;

public class StackWithMin extends Stack<Integer> {
	Stack<Integer> minStack;

	public StackWithMin() {
		minStack = new Stack<Integer>();
	}
	public void push(int val) {
		super.push(val);
		if(minStack.isEmpty() || minStack.peek() >= getMin()){
			minStack.push(val);
		}
	}

	public Integer pop(){
		int value = super.pop();
		if(value == getMin()){
			minStack.pop();
		}
		return value;
	}

	public int getMin() {
		if(minStack.isEmpty()) {
			return Integer.MAX_VALUE;
		} else {
			return minStack.peek();
		}
	}
}


2,用队列实现一个堆栈

借用两个队列,实现堆栈后进先出的原理。代码如下:
import java.util.LinkedList;
import java.util.Queue;

public class MyStack {
	Queue<Integer> q1 = new LinkedList<Integer>();
	Queue<Integer> q2 = new LinkedList<Integer>();
	
	public void push(int val) {
		q1.offer(val);
	}
	
	public int pop() {
		while(q1.size() > 1) q2.offer(q1.poll());
		int result = q1.poll();
		Queue<Integer> q = q1;
		q1 = q2;
		q2 = q1;
		return result;
	}
	
	public int peek() {
		while(q1.size() > 1) q2.offer(q1.poll());
		int result = q1.poll();
		q2.offer(result);
		Queue<Integer> q = q1;
		q1 = q2;
		q2 = q;
		return result;
	}
	
	public boolean isEmpty() {
		if(q1.size() == 0) {
			return true;
		} else {
			return false;
		}
	}

}


3,用堆栈实现队列
思路和上一题类似,这里用两个堆栈来实现队列先进先出的原理。代码如下:
import java.util.Stack;

public class MyQueue {
	Stack<Integer> stack1 = new Stack<Integer>();
	Stack<Integer> stack2 = new Stack<Integer>();
	
	public void offer(int val) {
		stack1.push(val);
	}
	
	public int element() {
		while(!stack1.isEmpty())
			stack2.push(stack1.pop());
		int result = stack2.pop(); //删除第一个元素
		while(!stack2.isEmpty())
			stack1.push(stack2.pop());
		return result;
	}
	
	public int peek() {
		while(!stack1.isEmpty())
			stack2.push(stack1.pop());
		int result = stack2.peek(); //不删除第一个的元素
		while(!stack2.isEmpty())
			stack1.push(stack2.pop());
		return result;
	}
	
	public boolean empty() {
		if(stack1.isEmpty())
			return true;
		return false;
	}
}

猜你喜欢

转载自kickcode.iteye.com/blog/2263592