【小白爬Leetcode225】2.1 用队列实现栈 Implement Stack using Queues
Leetcode 225 e s a y \color{#228B22}{esay} esay
点击进入原题链接:Leetcode225 用队列实现栈 Implement Stack using Queues
题目
Description
Implement the following operations of a stack using queues.
· push(x) – Push element x onto stack.
· pop() – Removes the element on top of the stack.
· top() – Get the top element.
· empty() – Return whether the stack is empty.
Example:
MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
stack.top(); // returns 2
stack.pop(); // returns 2
stack.empty(); // returns false
Notes:
You must use only standard operations of a queue – which means only push to back
, peek/pop from front
, size
, and is empty
operations are valid.
Depending on your language, queue may not be supported natively. You may simulate a queue by using a list
or deque
(double-ended queue), as long as you use only standard operations of a queue.
You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).
中文描述
使用队列实现栈的下列操作:
· push(x) – 元素 x 入栈
· pop() – 移除栈顶元素
· top() – 获取栈顶元素
· empty() – 返回栈是否为空
注意:
你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
思路一 改变push的位置【push O(n),pop O(1)】
stack和queue的区别可以理解为push
的位置不同:
stack
的push
添加到栈顶;
queue
的push
是添加到队尾;
因此一个朴素的思想是:
改变queue push
的位置,每次push
元素的时候都push
到front
的位置,这样queue
也变成了顶部进入,顶部弹出, 实质上就是stack了,剩下的pop
,top
,empty
直接沿用就好了。
改变push的操作如下:
- 先新建一个临时的空队列
temp
,把要新增的元素x放入。
std::queue<int> temp;
temp.push(x);
- 将已有的数据
_data
放入temp
中,同时置空_data。此时就实现了x的头部插入。
while(!_data.empty()){
temp.push(_data.front());
_data.pop();
}
- 再将
temp
复制给空的_data
即可。
这里我本来写的是这样的:
while(!temp.empty()){
_data.push(temp.front());
temp.pop();
}
后来想了一下,这是何必呢,直接_data = temp
不就行了…,反正temp
在函数push()
生命周期结束之后就释放了。
完整代码如下:
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
std::queue<int> temp;
temp.push(x);
while(!_data.empty()){
temp.push(_data.front());
_data.pop();
}
_data = temp;
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int res = _data.front();
_data.pop();
return res;
}
/** Get the top element. */
int top() {
return _data.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return _data.empty();
}
private:
std::queue<int> _data;
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
思路2 改变pop的位置 【push O(1),pop O(n)】
这个方法通过改变pop的位置来实现queue到stack的转换。
push不变,将每次pop的元素从队列头部front
改成队列尾部元素back
。这个方法需要用到长度,因此int length
来记录_data
的长度。
改变的方法是:
- 先记录一下要返回的值
int res = _data.back()
; - 用一个临时队列
temp
接收_data
的第一个到倒数第二个元素,同时不断弹出_data
;
std::queue<int> temp;
for(int i=0;i<length-1;i++)
{
temp.push(_data.front());
_data.pop();
}
- 将
_data
的最后一个元素弹出,实现_data
的清空,并减少长度;注意,有可能_data
已经是空的了,所以要加个if判断条件;
if(!_data.empty()) _data.pop();
length--;
- 紧接着将
temp
的元素复制回_data
;
_data = temp;
return res
。
至于push
,多加一个length++
即可,相应地top
应该返回_data.back()
而不是_data.front()
,empty
不用变。
完整代码如下:
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
_data.push(x);
length++;
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
std::queue<int> temp;
int res = _data.back();
for(int i=0;i<length-1;i++)
{
temp.push(_data.front());
_data.pop();
}
_data = temp;
return res;
}
/** Get the top element. */
int top() {
return _data.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return _data.empty();
}
private:
std::queue<int> _data;
int length = 0;
};
后来想了一下,queue
不是自带.size()
么,我还额外维护一个length
是何必呢…
思路3 push完反转queue 【push O(n),pop O(1)】
和思路1的基本思路一样,但在实现上节省了一个temp
的空间(即只用一个queue
即_data
)
pop的过程是这样的:
图片来源:官方解答
完整代码如下:
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
_data.push(x);
int length = _data.size();
for(int i=0;i<length-1;i++)
{
int temp = _data.front();
_data.pop();
_data.push(temp);
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int res = _data.front();
_data.pop();
return res;
}
/** Get the top element. */
int top() {
return _data.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return _data.empty();
}
private:
std::queue<int> _data;
};