用两个栈实现队列
- 题目描述
- 数据范围
- 示例
- 代码实现
- 1. 代码思路
- `push` 操作:
- `pop` 操作:
- 2. 代码实现
- 3. 代码解析
- 4. 时间复杂度与空间复杂度
- 总结
题目描述
用两个栈来实现一个队列,使用 n 个元素来完成 n 次在队列尾部插入整数(push)和 n 次在队列头部删除整数(pop)的功能。队列中的元素为 int 类型。保证操作合法,即保证 pop 操作时队列内已有元素。
数据范围
- 操作次数 n n n 满足 0 ≤ n ≤ 1000 0 \leq n \leq 1000 0≤n≤1000
- 队列中的元素范围为 ∣ v a l ∣ ≤ 10000 |val| \leq 10000 ∣val∣≤10000
- 要求:存储
n个元素的空间复杂度为 O ( n ) O(n) O(n),插入与删除的时间复杂度为 O ( 1 ) O(1) O(1)。
示例
输入1:
["PSH1", "PSH2", "POP", "POP"]
输出1:
1, 2
解析:
"PSH1":将1插入队列尾部"PSH2":将2插入队列尾部"POP":删除一个元素,先进先出 => 返回1"POP":删除一个元素,先进先出 => 返回2
输入2:
["PSH2", "POP", "PSH1", "POP"]
输出2:
2, 1
代码实现
1. 代码思路
- 使用两个栈
stack1和stack2来模拟队列。 stack1用于存储入队操作的元素。stack2用于存储出队操作时,从stack1中转移过来的元素。
push 操作:
- 直接将元素压入
stack1。
pop 操作:
- 如果
stack2为空,则将stack1中的所有元素转移到stack2中,这样stack2的栈顶就是最早进入队列的元素。 - 如果
stack2不为空,直接从stack2弹出栈顶元素。
2. 代码实现
#define MAX_SIZE 1000 // 假设栈最大容量
int stack1[MAX_SIZE];
int stack2[MAX_SIZE];int top1 = 0; // 插入栈栈顶指针
int top2 = 0; // 删除栈栈顶指针// 入队操作
void push(int node) {if (top1 < MAX_SIZE) {stack1[top1++] = node; // 将元素压入 stack1}
}// 出队操作
int pop() {// 如果 stack2 为空,将 stack1 中的元素倒入 stack2if (top2 == 0) {while (top1 > 0) {stack2[top2++] = stack1[--top1]; // 将 stack1 中的元素倒入 stack2}}// 如果 stack2 不为空,正常弹出栈顶元素if (top2 > 0) {return stack2[--top2]; // 弹出 stack2 的栈顶元素}return -1; // 当栈为空时返回 -1
}
3. 代码解析
-
push函数:- 该函数将一个整数
node压入stack1,作为队列的尾部元素。
- 该函数将一个整数
-
pop函数:- 如果
stack2为空,说明当前队列中没有待出队的元素,我们需要将stack1中的元素逐一移入stack2,以确保stack2的栈顶为最早入队的元素。 - 如果
stack2不为空,则直接从stack2中弹出栈顶元素,这样确保了队列的先进先出特性。
- 如果
4. 时间复杂度与空间复杂度
-
时间复杂度:
push操作时间复杂度为 O ( 1 ) O(1) O(1),因为我们只是将元素压入stack1。pop操作的最坏时间复杂度为 O ( n ) O(n) O(n),当stack2为空时,需要将stack1中的所有元素转移到stack2,不过每个元素最多被移动一次,因此在所有操作完成后的平均时间复杂度是 O ( 1 ) O(1) O(1)。
-
空间复杂度:
- 由于我们使用了两个栈,因此空间复杂度是 O ( n ) O(n) O(n),其中
n是队列中元素的个数。
- 由于我们使用了两个栈,因此空间复杂度是 O ( n ) O(n) O(n),其中
总结
整体上这题还是比较简单的,没什么难度,只要懂了思路还是很好实现的,最开始花了很多时间去实现栈,结果发现,卧槽怎么没有栈,没有主函数,原来只需要模拟栈即可。反正只要记住一个用来进入,一个用来出去,只要第二个栈空了,就把第一个倒进去。