从零学算法
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
232.请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作push、pop、peek、empty
实现 MyQueue 类
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空返回 true 否则返回 false
说明
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque双端队列来模拟一个栈只要是标准的栈操作即可。
示例 1
输入
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出
[null, null, null, 1, 1, false]
解释
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
- 我的思路比较蠢用两个栈第一个栈 A 就正常 push等于逆序存储了队列的值在 push 或 peek 时把栈 A 的值 pop 并 push 到另一个栈 B栈 B 存储的就是正确顺序的队列的值pop 或 peek 完了之后再把 B 的 pop 回 A。
-
class MyQueue { Stack<Integer> stack = new Stack<>(); Stack<Integer> queue = new Stack<>(); public MyQueue() { } public void push(int x) { stack.push(x); } public int pop() { while(!stack.isEmpty()){ queue.push(stack.pop()); } int val = queue.pop(); while(!queue.isEmpty()){ stack.push(queue.pop()); } return val; } public int peek() { while(!stack.isEmpty()){ queue.push(stack.pop()); } int val = queue.peek(); while(!queue.isEmpty()){ stack.push(queue.pop()); } return val; } public boolean empty() { return stack.isEmpty(); } }
- 但是如果连续多次 pop 或 peek 时其实我们不需要每次都把数据来回倒腾一遍定义一个布尔值记录当前是否是顺序存储pop 或 peek 如果不为顺序就搞成顺序否则直接 pop 或 peek 即可push 时如果为顺序就再倒腾回来否则直接 push。
-
class MyQueue { Stack<Integer> stack = new Stack<>(); Stack<Integer> queue = new Stack<>(); boolean isAsc; public MyQueue() { } public void push(int x) { if(isAsc){ isAsc = false; while(!queue.isEmpty()){ stack.push(queue.pop()); } } stack.push(x); } public int pop() { if(isAsc){ return queue.pop(); } isAsc = true; while(!stack.isEmpty()){ queue.push(stack.pop()); } return queue.pop(); } public int peek() { if(isAsc){ return queue.peek(); } isAsc = true; while(!stack.isEmpty()){ queue.push(stack.pop()); } return queue.peek(); } public boolean empty() { return stack.isEmpty() && queue.isEmpty(); } }
+在上面我之所以一旦在 pop 或 peek 操作后再 push就要把元素重新从 queue pop 回 stack就是为了保持 stack 的倒序存储保证了 stack 的倒序在需要 pop 或 peek 就能重新 pop 回 queue保证了 queue 的顺序存储。但是实际上不需要这么复杂当遇到 pop 或 peek 操作时只要 queue 为空就把 stack 的元素都 pop 到 queue当 push 时就只需要正常 push 到 stack 即可这样的话当你 pop 或 peek 时你只有把之前顺序存储的元素用完了才会再从 stack 取元素。用完了才再填充这一件事就是保持 stack 和 queue 按照正确顺序存储元素的关键。比如正常入队元素为 [1,2,3]stack 在 push 完 [1,2] 后为 [2,1]这时我 popqueue 就开始填充为 [1,2]然后 pop 出 1 剩余 [2]stack 此时为 []如果我 push 完 3 后再 pop直接就再把 3 填充到 queue 的 [2]就成了[3,2] 然后 pop queue 的 3实际上应该 pop 2 才对而我把 queue 用完上一轮正确存储的元素再存储后就保证了使用 queue 的元素时顺序都是正确的也就是先 pop 了 1, 然后 pop 2等到没东西 pop 了才把 stack 的 3 拿过来 pop。
-
Stack<Integer> stack = new Stack<>(); Stack<Integer> queue = new Stack<>(); public MyQueue() { } public void push(int x) { stack.push(x); } public int pop() { fillQueue(); return queue.pop(); } public int peek() { fillQueue(); return queue.peek(); } public boolean empty() { return stack.isEmpty() && queue.isEmpty(); } public void fillQueue(){ if(queue.isEmpty()){ while(!stack.isEmpty()){ queue.push(stack.pop()); } } }
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |