当前位置: 首页 > news >正文

算法-每日一题(DAY15)用队列实现栈

1.题目链接

225. 用队列实现栈 - 力扣(LeetCode)

2.题目描述

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

1 <= x <= 9
最多调用100 次 push、pop、top 和 empty
每次调用 pop 和 top 都保证栈不为空

3.解题思路

对于这道题我们使用了两个队列(q1 和 q2)的双队列策略。初始化时,两个队列为空。对于入栈操作(push),元素直接被推入队列 q1。出栈操作(pop)则通过将队列 q1 中的所有元素逐个转移到队列 q2 中,直到 q1 中只剩下一个元素,这样单独剩下的元素即为要弹出的栈顶元素。随后将 q2 中的元素全部转回 q1,保持队列的栈结构。获取栈顶元素(top)的方法直接返回 q1 的最后一个元素。检查栈是否为空(empty)则简单地返回 q1 是否为空。通过这种方法,栈的基本操作得以利用队列的特性有效地实现,灵活地保持了后进先出的原则。

更通俗的讲,想象你有两个箱子(q1 和 q2)。你将东西(元素)从箱子 q1 放入箱子 q2,但是你不想每次都手动把东西搬回去。所以每当你从栈里拿东西时,你就把 q1 里的东西搬到 q2,直到剩下一个东西,然后那就是栈顶元素。拿出栈顶元素后,把 q2 的东西再搬回 q1,让栈继续运作。

4.题解代码

class MyStack {
public:queue<int> q1, q2; // 定义两个队列 q1 和 q2,用于实现栈的功能MyStack()// 构造函数,初始化栈{}void push(int x)// push 函数:将元素 x 压入栈中{q1.push(x);// 直接将元素 x 添加到队列 q1 的末尾}int pop()// pop 函数:从栈中弹出元素并返回{// 将 q1 中的元素全部移到 q2,直到 q1 剩下最后一个元素while (q1.size() > 1) {// 将 q1 的前面的元素移动到 q2q2.push(q1.front());q1.pop();} int res = q1.front();// 保存 q1 中的最后一个元素(栈顶元素)q1.pop(); // 弹出栈顶元素(即来自 q1 的最后一个元素)q1 = q2;// 将 q2 中的元素全部移动回 q1while (!q2.empty()) {q2.pop();// 清空 q2,准备下一次操作}return res;// 返回被弹出的元素}int top()// top 函数:返回栈顶的元素但不弹出它{return q1.back();// 由于 q1 是在 push 时添加元素的,top 方法直接访问 q1 队列中的最后一个元素}bool empty()// empty 函数:检查栈是否为空{return q1.empty();// 通过检查 q1 是否为空来判断栈是否为空}
};

5.示例演算

步骤操作队列1状态 (队首← →队尾)队列2状态 (队首← →队尾)栈状态 (栈底← →栈顶)操作详情说明
初始-[][][]初始状态
1push(1)[1][][1]将1加入队列1
2push(2)[1,2][][1,2]将2加入队列1
3push(3)[1,2,3][][1,2,3]将3加入队列1
4pop()[][1,2][1,2]关键步骤
1. 将队列1前n-1个元素(1,2)转移到队列2
2. 弹出队列1的最后一个元素(3)
5push(4)[][1,2,4][1,2,4]将4加入当前非空队列(队列2)
6pop()[1,2][][1,2]关键步骤
1. 将队列2前n-1个元素(1,2)转移到队列1
2. 弹出队列2的最后一个元素(4)
7pop()[1][][1]关键步骤
1. 将队列1前n-1个元素(1)转移到队列2
2. 弹出队列1的最后一个元素(2)

6.复杂度计算

时间复杂度:

操作时间复杂度说明
pushO(1)直接插入队列末尾
popO(n)需要转移n−1个元素 + 队列深拷贝O(n) + 清空队列O(n)
topO(1)直接访问队列尾部元素
emptyO(1)简单判断队列是否为空

空间复杂度:总空间复杂度为 O(n),因为两个队列最多同时存储 n 个元素(在执行 push 操作时会临时存储)。此外,额外空间复杂度为 O(1),因为指针的交换和操作不需要额外的存储开销。

http://www.xdnf.cn/news/1371349.html

相关文章:

  • 算法练习——26.删除有序数组中的重复项(golang)
  • Swift 解法详解 LeetCode 363:矩形区域不超过 K 的最大数值和
  • Spring Bean 生命周期高阶用法:从回调到框架级扩展
  • Java基础第5天总结(final关键字,枚举,抽象类)
  • CVPR自适应卷积的高效实现:小核大感受野提升复杂场景下图像重建精度
  • vue新增用户密码框自动将当前用户的密码自动填充的问题
  • 高校党建系统设计与实现(代码+数据库+LW)
  • 嵌入式配置数据序列化:自定义 TLV vs nanopb
  • 深度学习篇---LeNet-5
  • 1Panel命令
  • 100种交易系统(6)均线MA识别信号与杂音
  • 深度学习----由手写数字识别案例来认识PyTorch框架
  • Python实现RANSAC进行点云直线、平面、曲面、圆、球体和圆柱拟合
  • Il2CppInspector 工具linux编译使用
  • 设计模式之命令模式
  • Vuex 和 Pinia 各自的优点
  • Linux之SELinux 概述、SSH 密钥登录、服务器初始化
  • 利用AI进行ArcGISPro进行数据库的相关处理?
  • Java数据结构速成【1】
  • 原则性 单一职责原则,第一性原则和ACID原则 : 安全/学习/节约
  • 从双重检查锁定的设计意图、锁的作用、第一次检查提升性能的原理三个角度,详细拆解单例模式的逻辑
  • Markdown学习笔记(4)
  • 矩阵微积分的链式法则(chain rule)
  • 在 Android Studio 中修改 APK 启动图标(2025826)
  • 从线到机:AI 与多模态交互如何重塑 B 端与 App 界面设计
  • 【RAGFlow代码详解-23】聊天系统架构
  • 【LeetCode 热题 100】75. 颜色分类——双指针
  • PWM控制实现呼吸灯
  • 家庭财务规划与投资系统的设计与实现(代码+数据库+LW)
  • Linux SSH 基于密钥交换的自动登录:原理与配置指南