用两个栈实现队列
- 题目描述
- 数据范围
- 示例
- 代码实现
- 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),其中
总结
整体上这题还是比较简单的,没什么难度,只要懂了思路还是很好实现的,最开始花了很多时间去实现栈,结果发现,卧槽怎么没有栈,没有主函数,原来只需要模拟栈即可。反正只要记住一个用来进入,一个用来出去,只要第二个栈空了,就把第一个倒进去。