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.
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).
s思路:
1. 再次说明,世界上的事物是紧密联系的,queue和stack都可以相互实现了!这题不难,应该用两个queue来实现一个stack的功能,也就是说两个queue==一个stack.
2. 两个queue的使用比较有意思,想了一会,发现一定要从最简单的case:只有一个数据,来模拟这个过程,不能随意假设现在里面有多个数据。在程序设计时,一定要从最简单的case入手,去发现规律。比如:我刚开始就想里面有4个数据,就不知道如何往下走,因为这4个数据的排列不是随意假设可以得到的。
3. 现从一个数据开始往queue放,假设两个queue,左边是主,右边是辅,先把1放入主,当放2时,放之前为保证2在主的头部,这样才能模拟stack,需要把主queue中的数据都读出来放在副queue里,所以把1读出,此时主queue空,然后写入2,之后在把副queue中的1再读出写入主queue;当放3的时候,也如法炮制,为保证把3写到主queue的头部,先清空主queue,把主queue的数读出写入副queue,然后把3写入主queue,最后再把副queue中的数据还原到主queue中,结束!此时在主queue中3个数的顺序就是3在顶,2在中间,1在底,这就和stack的特征一致。
4. 现在分析,为了用queue模拟stack,首先空间上,需要两个queue,一个主一个副;时间上,当queue里本来就有k个数,要写入新的数时,需要先把k个数读出主queue,再写入副queue,然后写入这个数,之后还要把这k个数读出副queue,同时写入主queue。因此,时间复杂度是o(k),和里面的数的个数成正比。因此,这样做时间空间都不划算!
5. 这么做的意义,在我看来,就是表面这两个一起学习,很多相似很多相反操作的数据结构如何可以联系到一起,也就是说站在某一个角度或者位置,看到这两者是相同的;其次,也看到了思维绝不是无根之木,不能随意从任何地方开始思考,需要从一个元问题入手,而通常元问题,又是问题的边界,在边界的地方,我们总有经验击破问题的barrier,一探问题的本质,所以从边界入手,从元问题入手,是最容易出结果的!
6. 从边界,从元问题入手,说起来容易,做起来还要多练习,不过道理上要先通达,做起来就目标明确,不会走偏,务虚和务实总是交叉进行,不分先后!
7. 看了答案,其实一个queue就够了,只要总原则是每次写完保证这个数在queue头部!看方法2
//方法1: 2个queue
class MyStack {
private:
queue<int> qq1,qq2;
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
if(!qq1.empty()){
while(!qq1.empty()){
int cur=qq1.front();
qq1.pop();
qq2.push(cur);
}
}
qq1.push(x);
if(!qq2.empty()){
while(!qq2.empty()){
int cur=qq2.front();
qq2.pop();
qq1.push(cur);
}
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int cur=qq1.front();
qq1.pop();
return cur;
}
/** Get the top element. */
int top() {
return qq1.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return qq1.empty();
}
};
/**
* 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: 1个queue足够
class MyStack {
private:
queue<int> qq;
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
int sz=qq.size();
qq.push(x);
while(sz--){
int cur=qq.front();
qq.pop();
qq.push(cur);
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int cur=qq.front();
qq.pop();
return cur;
}
/** Get the top element. */
int top() {
return qq.front();
}
/** Returns whether the stack is empty. */
bool empty() {
return qq.empty();
}
};