思路:
想到之前用栈模拟队列的题目(232题)用了两个栈,一个主栈,一个辅助栈,这个题目里直接提示用两个队列,想必第二个队列的功能应该也是类似于辅助的功能。(联想)
这样就可以先写出empty()的代码,类似232,只有都空才是真空,所以可以先写出来这个函数的答案;
如果选q1作为主队列,那么push的时候就push到q1里去,push()写好了;
主要是pop的思路:举push 1,2,3再pop()的例子。如果是栈,现在pop的应该是3,但是队列没有这种操作,所以就要用到辅助队列q2了。那么目标元素是3,它被包含在q1中,所以pop要模拟的功能就是:在正确保存其他元素的相对顺序的同时把3从q1中移除。所以,采取的操作就是把3之前的所有元素都移动到另一个队列中,只留下3,这个时候再移除3并返回即可。
这也是这道题和232的不同之处,在这样操作之后,q1和q2的主次顺序变化了,并且q1现在是空队列。不难想到,如果再进行类似的操作,那么它们的顺序就又会变回来,所以这道题的两个队列是不断变化的。正因如此,在进行top()的时候就要注意队列为空的情况,在上面,我们让push操作永远由q1执行,这意味着q1的元素永远都是最“新鲜”的,如果q1里有元素,那么它一定是新push进来的,top直接返回q1最后一个元素即可,如果q1是空的,说明刚进行了转移操作,这个时候就返回q2最后的元素。
代码如下:
class MyStack {
public:
queue<int> q1,q2;
MyStack() {
}
void push(int x) {
q1.push(x);
}
int pop() {
if(q2.empty())
{
while(q1.size() != 1)
{
int x = q1.front();
q1.pop();
q2.push(x);
}
int x = q1.front();
q1.pop();
return x;
}
else
{
while(q2.size() != 1)
{
int x = q2.front();
q2.pop();
q1.push(x);
}
int x = q2.front();
q2.pop();
return x;
}
}
int top() {
return q1.empty()? q2.back() : q1.back();
}
bool empty() {
return q1.empty() && q2.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();
*/
优化思路:
只使用一个队列也是可以的,这时别的函数就都很简单,只需要注意pop()怎么写就行了。因为pop()最根本的东西没有变,还是想办法把back()的元素抛出队,而此时没有备用队列,所以就需要把back()变成front(),同时不能丢失队列里的其它元素——可以想象一个动画,元素不断地向前移动,直到队尾变队首:是不是很熟悉?是的,这里可以借鉴数据结构循环队列的思想,不断进行循环,让队头元素先出队再入队,这样就可以慢慢向前移动了,直到目标元素成为队头,这时就会了!
代码如下:
class MyStack {
public:
queue<int> q;
MyStack() {
}
void push(int x) {
q.push(x);
}
int pop() {
int x = q.back();
while(q.front() != x)
{
int temp = q.front();
q.pop();
q.push(temp);
}
q.pop();
return x;
}
int top() {
return q.back();
}
bool empty() {
return q.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();
*/