1.用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
解题思路:
一个栈当队头,另一个栈当队尾
- 当调用appendHead时,将元素直接插入队尾栈
- 当调用deleteHead时,若队头栈不为空,则直接弹出队头栈的栈顶元素;若队头栈为空,则将队尾栈的所有元素压入队头栈,然后队头栈再弹出栈顶元素;若两个栈都为空,返回-1
代码如下:
class CQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
public CQueue(){
stack1=new Stack<>();
stack2=new Stack<>();
}
public void appendTail(int value) {
stack1.push(value);
}
public int deleteHead() {
if(stack1.isEmpty()&&stack2.isEmpty()){
return -1;
}
if(!stack2.isEmpty()){
return stack2.pop();
}else {
while (!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
2.包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
解题思路:
解法1:
- 申请两个栈,主栈用于存储加入栈的元素,辅助栈用于存储每个元素入栈时的当前最小元素
- 当调用pop函数时,主栈和辅助栈各出栈一个元素,主栈弹出的元素返回,辅助栈的释放
- 调用push函数时,将元素压入主栈,对比当前元素和辅助栈的栈顶元素,谁小压谁
代码如下:
private Stack<Integer> stack1;
private Stack<Integer> stack2;
public MinStack() {
stack1=new Stack<>();
stack2=new Stack<>();
}
public void push(int x) {
if(stack2.isEmpty()||stack2.peek()>x){
stack2.push(x);
}else {
stack2.push(stack2.peek());
}
stack1.push(x);
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack1.peek();
}
public int min() {
return stack2.peek();
}
解法2:
- 使用链表结构
- 给节点加入min属性,min属性记录当前链表的最小值
- 利用头插法实现push函数
class Node{
int value;
int min;
Node next;
public Node(int value, int min) {
this.value = value;
this.min = min;
}
}
Node head=null;
public MinStack() {
}
public void push(int x) {
if(head==null){
head=new Node(x,x);
}else {
Node cur=new Node(
x,x>head.min?head.min:x
);
cur.next=head;
head=cur;
}
}
public void pop() {
head=head.next;
}
public int top() {
return head.value;
}
public int min() {
return head.min;
}