题目 剑指offer09题 : 时间换空间
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,
分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
例1:
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
例2:
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
代码界面还有一行意思是这个解题类如何被调用结合上面的示例。
说明输入下面第一行其实是函数/方法的调用顺序。这样我们只需要定义好类的属性实现这个类的行为方式就好了
/**
* Your CQueue object will be instantiated and called as such:
* CQueue obj = new CQueue();
* obj.appendTail(value);
* int param_2 = obj.deleteHead();
*/
解题思路
这道题是一道非常简单的题目;只需要了解栈、队列的元素增删特性就可以做出来
栈:元素后进先出;最后被压入栈中处于栈的顶层,最先被弹出(类似于弹夹,最后被压入的最先被发射出)
队列: 元素先进先出;就和现实中的排队一样,先进队的先出队(类似医院缴费排队)
由于有两个栈辅助配合实现队列;那么可以将一个栈只用于进队操作(原始栈);一个栈只用于出队操作(反转栈);
当执行到出队操作时,反转栈为空,则将原始栈的数据一个个弹出,加入反转栈。这时队头的数据则会出现在反转栈的栈顶这时只需直接弹出即可;
原始栈:按顺序压入 5 3 1.栈顶是1是队尾,5是队头
[ 1 , 3 , 5]
这时进行将数据压入反转站: 反转栈的栈顶是5,即队头。这时执行栈的pop操作即可。
[5 , 3 , 1]
两个栈各司其职,当反转栈为空时只需去原始栈将数据取出压入即可
题解
/**
* @ClassName LKJZOF09
* @Description TODO 力扣剑指offer 09
* @Author HeXiaoyuan
* @Date 2020-07-23 23:39
*/
public class LKJZOF09 {
//原始栈
private Stack<Integer> originStack;
//反转栈
private Stack<Integer> revertStack;
public LKJZOF09() {
originStack = new Stack<>();
revertStack = new Stack<>();
}
public void appendTail(int value) {
originStack.push(value);
}
public int deleteHead() {
Integer result = -1;
if(!revertStack.empty()){
result = revertStack.pop();
}else if(!originStack.empty()){
revert();
result = revertStack.pop();
}
return result;
}
//当反转栈没有可弹出数据时则将原始栈中的数据压入反转栈
private void revert(){
while (!originStack.empty()){
revertStack.push(originStack.pop());
}
}
}
题目 232题: 用栈实现队列 : 空间换时间
使用栈实现队列的下列操作:
push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。
示例:
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
说明:
你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
解题思路
还是了解到栈和队列对于元素操作的特性就好了。
关于队列最关键的就是队首和队尾,所以只要在进行队列元素操作时定位好队首和队尾就可以将队列实现出来
队首:在有索引的情况下,删除的时候队首出队,队首的位置索引后移
队尾:在有索引的情况下,增加元素,队尾的位置索引后移
题解
class MyQueue {
List<Integer> original;
Integer head = 0 , tail = -1;
/** Initialize your data structure here. */
public MyQueue() {
original = new ArrayList<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
original.add(x);
tail ++;
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
Integer result = original.get(head);
head++;
return result;
}
/** Get the front element. */
public int peek() {
return original.get(head);
}
/** Returns whether the queue is empty. */
public boolean empty() {
if(head>tail){
return true;
}
return false;
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/