题目链接地址:
题目描述:
用两个栈来实现一个队列,完成队列的Push和Pop操作。
队列中的元素为int类型。
输入:
每个输入文件包含一个测试样例。
对于每个测试样例,第一行输入一个n(1<=n<=100000),代表队列操作的个数。
接下来的n行,每行输入一个队列操作:
1. PUSH X 向队列中push一个整数x(x>=0)
2. POP 从队列中pop一个数。
输出:
对应每个测试案例,打印所有pop操作中从队列pop中的数字。如果执行pop操作时,队列为空,则打印-1。
样例输入:
3
PUSH 10
POP
POP
样例输出:
10
-1
解题思路:
用两个栈来实现一个队列,完成队列的Push和Pop操作。刚开始看到这道题的时候,我的想法是先开两个栈s1和s2,s1用来存放入队操作Push所对应的元素,s2用来存放出队操作Pop所对应的元素。如果遇到Push操作,先判断s2中是否有元素,如果s2中有元素,就将s2栈中的元素全部倒入到s1栈中,再将入队元素插入到s1的栈顶;如果遇到Pop操作,就先将s1栈中的元素全部倒入到s2栈中,然后再弹出s2栈的栈顶元素。简单来说,就是开两个栈,然后将这两个栈中的元素“倒来倒去”以实现队列的Push和Pop操作。但是这种算法TLE了 囧 。。。
后来和范神讨论,范神给了我一个巧妙的算法,避免了“倒来倒去”的过程。这个算法大概思想是开两个栈s1和s2,如果遇到Push操作则直接将入队元素压入到s1栈中;如果遇到Pop操作则直接弹出s2栈的栈顶元素(只有当s2栈为空时,才将s1中的元素压入到s2中,这样就避免了“倒来倒去”的现象)。这种算法的本质就是s1栈从栈底到栈顶依次保存队列的后半段,s2栈从栈顶到栈底依次保存队列的前半段。请脑补这样的画面:s1栈的栈底与s2的栈底连在了一起,然后都横着摆放共同组成了一个队列。
具体的样子请看图1:
图1 s1栈和s2栈拼接形成的队列
如果连续执行Pop操作弹出元素1,2,3,4,栈s2将变成空栈,
如图2所示:
图2 s2栈为空的情况
这时如果再执行Pop操作,要先将s1栈中的元素全部弹入到s2栈中,再执行Pop操作,
具体如图3所示:
图3 将s1栈中的元素全部弹入到s2栈中
如果执行的是Push操作,只需将入队元素压入到s1栈即可,
如图4所示:
图4 执行Push操作,将入队元素直接压入到s1栈中
这样就巧妙地利用s1栈和s2栈高效地实现了一个队列。
AC代码如下:
#include<stdio.h>
#include<string.h>
#include<stack>
using namespace std;
/**
* 队列的入队元素直接压入s1栈,队列出队元素直接从s2栈弹出
* s1栈从栈底到栈顶依次保存队列的后半段,s2栈从栈顶到栈底依次保存队列的前半段
* 在执行出队操作时,只有当s2栈为空时,才将s1栈中的元素全部倒入s2栈中
* 这样就不会出现"倒来倒去"的现象
* @param n 代表队列操作的个数
* @return void
*/
void twoStackToOneQueue(int n)
{
stack <int> s1; // s1的栈顶元素保存着队列的队尾元素
stack <int> s2; // s2的栈顶元素保存着队列的队首元素
int i = 0;
int x;
char operation[20]; // 记录操作
while(i < n)
{
scanf("%s",operation);
if(0 == strcmp(operation,"PUSH")) // 将元素压入队尾 PUSH x
{
scanf("%d",&x);
s1.push(x); // 执行入队操作
}
else // 将队首元素弹出 POP
{
if(true == s2.empty()) // 如果s2为空,则将s1中的元素全部弹入到s2中,否则直接跳过次语句块
{
while(true != s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
if(true != s2.empty()) // 如果s2不为空 则输出并弹出s2的栈顶元素
{
printf("%d\n",s2.top());
s2.pop();
}
else // 如果s2为空,则输出-1
{
printf("-1\n");
}
}
i++;
}
}
int main()
{
int n;
scanf("%d",&n);
twoStackToOneQueue(n);
return 0;
}
/**************************************************************
Problem: 1512
User: blueshell
Language: C++
Result: Accepted
Time:70 ms
Memory:1184 kb
****************************************************************/