跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

栈的压入弹出序列验证算法详解

栈的压入弹出序列验证问题可通过模拟栈操作解决。核心逻辑是利用辅助栈按顺序压入元素,并即时检查栈顶是否与弹出序列期望值匹配。若匹配则弹出,否则继续压栈。最终栈空即表示序列合法。该方案时间复杂度 O(n),空间复杂度 O(n),是处理此类序列匹配问题的标准解法。

baireiraku发布于 2026/3/16更新于 2026/6/1626 浏览
栈的压入弹出序列验证算法详解

栈的压入弹出序列验证算法详解

给定两个整数序列,一个是压栈顺序 pushV,另一个是待验证的弹栈顺序 popV。我们需要判断 popV 是否可能是 pushV 对应的合法弹栈序列。

核心思路

解决这个问题的关键在于理解栈的后进先出(LIFO)特性。我们不需要真的去尝试所有可能的组合,而是可以通过模拟整个压栈和弹栈的过程来验证。

具体策略如下:

  1. 按序压栈:按照 pushV 的顺序依次将元素压入辅助栈。
  2. 即时匹配:每次压栈后,检查栈顶元素是否与 popV 当前期望弹出的元素一致。
  3. 贪心弹出:如果一致,立即弹出栈顶元素,并移动 popV 的指针继续检查下一个;如果不一致,则继续压入下一个元素。
  4. 最终判定:当所有元素都处理完毕后,如果辅助栈为空,说明序列合法;否则不合法。

这种模拟方法利用了贪心思想,一旦栈顶匹配就立刻弹出,因为栈的特性决定了如果现在不弹,后续更深的元素就无法在需要时先出来。

代码实现

下面是基于 C++ STL 的实现,使用了 std::stack 和双指针技巧。

#include <vector>
#include <stack>
using namespace std;

class Solution {
public:
    bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
        // 边界检查:长度不一致直接返回 false
        if (pushV.size() != popV.size()) {
            return false;
        }
        
        stack<int> st;
        size_t _push = 0; // 指向当前要压入的元素索引
        size_t _pop = 0;  // 指向当前要弹出的元素索引
        
        // 遍历所有需要压入的元素
         (_push < pushV.()) {
            
            st.(pushV[_push++]);
            
            
            
             (!st.() && st.() == popV[_pop]) {
                _pop++;      
                st.();    
            }
        }
        
        
         st.();
    }
};
while
size
// 将当前元素压入栈中
push
// 检查栈顶元素是否与当前期望弹出的元素匹配
// 如果匹配,则连续弹出所有匹配的元素
while
empty
top
// 移动弹栈序列指针
pop
// 弹出栈顶元素
// 如果所有元素都能正确弹出,栈应该为空
return
empty

执行过程模拟

为了更直观地理解,我们以 pushV = [1, 2, 3, 4, 5] 和 popV = [4, 5, 3, 2, 1] 为例。

初始状态:栈为空,_push 指向 1,_pop 指向 4。

  1. 压入 1, 2, 3:栈变为 [1, 2, 3]。此时栈顶 3 不等于目标 4,继续。
  2. 压入 4:栈变为 [1, 2, 3, 4]。栈顶 4 等于目标 4,匹配!
    • 弹出 4,栈变为 [1, 2, 3],_pop 指向 5。
  3. 压入 5:栈变为 [1, 2, 3, 5]。栈顶 5 等于目标 5,匹配!
    • 弹出 5,栈变为 [1, 2, 3],_pop 指向 3。
  4. 循环检查:此时栈顶 3 等于目标 3,无需再压栈,直接弹出。
    • 弹出 3,栈变为 [1, 2],_pop 指向 2。
    • 弹出 2,栈变为 [1],_pop 指向 1。
    • 弹出 1,栈变为 [],_pop 超出范围。

最终栈为空,返回 true,验证通过。

复杂度分析

  • 时间复杂度:O(n)。虽然代码中有嵌套循环,但每个元素最多被压入一次、弹出一次。主循环遍历 pushV,内层循环负责弹出,整体操作次数与元素总数成正比。
  • 空间复杂度:O(n)。最坏情况下(例如完全逆序),辅助栈需要存储所有 n 个元素。

边界情况处理

在实际开发中,还需要注意以下特殊情况:

  1. 空序列:如果两个序列都为空,逻辑上视为匹配,返回 true。
  2. 长度不等:如果输入的两个序列长度不同,显然不可能构成合法的栈变换,应提前返回 false。
  3. 单元素:单个元素的序列只要值相同即合法,不相同则非法。

总结

这道题是数据结构中关于栈的经典应用。通过引入辅助栈进行实时模拟,我们可以高效地验证序列合法性。掌握这种'模拟 + 贪心'的思路,对于解决类似的栈操作问题非常有帮助。核心在于利用栈的 LIFO 特性,一旦发现匹配机会就立即执行,避免不必要的回溯或复杂计算。

目录

  1. 栈的压入弹出序列验证算法详解
  2. 核心思路
  3. 代码实现
  4. 执行过程模拟
  5. 复杂度分析
  6. 边界情况处理
  7. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Ubuntu 下 llama.cpp 编译与性能调优实战
  • Stable Diffusion 商业级出图云端部署实战
  • 大语言模型联邦微调综述:挑战、方法与未来方向
  • 自然语言处理在医疗领域的应用与实战
  • GitHub 44K Star Skills:开源智能体技能库与自定义开发指南
  • 多种页面动画效果实现:星空、时钟与粒子特效
  • 自主无人机硬件搭建及 EGOPlanner 实现
  • 【机器人】具身导航 VLN 最新论文汇总 | Vision-and-Language Navigation
  • Python 数据可视化的 3 个核心步骤与实战指南
  • UART 协议演进中的波特率容错设计哲学
  • Angular 核心包解析:platform-browser 与 dynamic 的底层分工
  • 龙虾机器人(OpenClaw)本地部署指南
  • Stable Diffusion 快速上手与本地部署指南
  • Vue 3 实战:10 个提升开发体验的核心技巧
  • Python转行经验分享
  • DeepSeek-R1 开源大模型推理优化实战方案
  • 从单机到分布式:Redis 在架构演进中的核心价值
  • GitHub 代码提交与远程部署指南:SSH 连接与分支冲突解决
  • 大模型定义、原理、应用及优缺点详解
  • 从 Copilot 到 Agentic:快手重构人 AI 流程研发铁三角实践

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online