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

前面讲到了如何用数组以及链表实现一个基本的堆栈和队列,这篇文章介绍如何实现一个可以在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;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值