题目链接地址:
九度OJ-题目1512:用两个栈实现队列
题目描述:
用两个栈来实现一个队列,完成队列的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 ****************************************************************/