C语言学习笔记20260706-栈的压入、弹出序列验证

C语言学习笔记20260706-栈的压入、弹出序列验证

1. 题目概述

给定两个整数序列,第一个序列表示栈的压入顺序pushed),第二个序列表示弹出顺序popped)。请判断第二个序列是否可能是该栈的合法弹出序列。假设压入栈的所有数字均不相等。

  • 输入 :多组测试数据。每组包含一个整数 nnn(序列长度),随后两行分别为 pushedpopped 序列。
  • 输出 :如果 popped 是合法的出栈序列,输出 "Yes",否则输出 "No"。

2. 核心算法:辅助栈模拟法

解决此类问题的标准方法是直接模拟栈的操作过程 。我们不需要穷举所有可能的出栈情况,只需按照给定的 pushed 顺序入栈,并尽可能地去匹配 popped 序列。

💡 贪心策略

当我们把元素压入栈后,如果发现栈顶元素恰好等于当前期望弹出的元素 (即 popped 序列中指针指向的元素),那么我们必须立即将其弹出。

  • 为什么? 因为如果不现在弹出,后续再压入新元素,这个栈顶元素就会被压在下面,永远无法在下一个时刻被弹出了。
  • 结论:只要栈顶匹配,就立刻弹出,直到不匹配或栈为空为止。

3. 代码逻辑详解

关键变量说明

变量 作用
pushed[] 存储入栈序列
popped[] 存储目标出栈序列
stk[] 辅助栈,用于模拟真实的入栈出栈过程
top 栈顶指针,指向栈顶元素的下一个位置
p 出栈指针 ,指向 popped 数组中当前需要匹配的元素下标

模拟流程

c 复制代码
// 遍历每一个入栈元素
for (int i = 0; i < n; i++) 
{
    // 1. 将 pushed[i] 压入辅助栈
    stk[top++] = pushed[i];

    // 2. 检查栈顶是否满足出栈条件
    // 只要栈不为空,且栈顶元素 == 当前待出栈元素(popped[p])
    while (top > 0 && stk[top - 1] == popped[p])
	{
        top--; // 执行出栈操作
        p++;   // 移动出栈序列的指针,准备匹配下一个
    }
}

结果判定

循环结束后,检查辅助栈的状态:

  • top == 0(栈为空):说明 pushed 中的所有元素都成功按照 popped 的顺序被弹出了 →\rightarrow→ Yes
  • top != 0(栈非空):说明还有元素卡在栈里无法按顺序弹出 →\rightarrow→ No

4. 复杂度分析

  • 时间复杂度 :O(N)O(N)O(N)。虽然代码中有双重循环(forwhile),但每个元素最多只会被压入栈一次、弹出栈一次。因此总操作次数是线性的。
  • 空间复杂度 :O(N)O(N)O(N)。需要一个辅助栈 stk 来存储中间状态,最坏情况下栈的大小为 NNN。

5. 完整代码实现

以下是基于你提供的代码整理的完整版本,增加了注释以便于理解:

c 复制代码
#include <stdio.h>

int main() 
{
    int q;
    if (scanf("%d", &q) != 1) return 0; // 读取测试组数

    // 使用 static 数组避免大数组导致栈溢出,适配 1e5 规模
    static int pushed[100010];
    static int popped[100010];
    static int stk[100010];

    while (q--)
	{
        int n;
        scanf("%d", &n);

        // 读入入栈序列
        for (int i = 0; i < n; i++)
            scanf("%d", &pushed[i]);

        // 读入出栈序列
        for (int i = 0; i < n; i++)
            scanf("%d", &popped[i]);

        int top = 0; // 栈顶指针
        int p = 0;   // popped 数组的索引指针

        // 开始模拟
        for (int i = 0; i < n; i++) 
	{
            // 1. 元素入栈
            stk[top++] = pushed[i];

            // 2. 贪心匹配:如果栈顶元素等于当前应该弹出的元素,则持续弹出
            while (top > 0 && stk[top - 1] == popped[p]) 
			{
                top--; // 出栈
                p++;   // 指向下一个待弹出元素
            }
        }

        // 3. 判断结果
        if (top == 0)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
相关推荐
渣渣灰飞2 小时前
MySQL 系统学习 第二阶段 第三章 DQL(Data Query Language)第二节:WHERE 条件查询
sql·学习·mysql
维他奶糖612 小时前
基于 DrissionPage 实现小红书搜索笔记批量采集
笔记
心中有国也有家3 小时前
AtomGit Flutter 鸿蒙客户端:E-Brufen 架构设计
学习·flutter·华为·harmonyos
hssfscv3 小时前
QT的学习笔记4——QMainWindow、资源文件以及主要控件的介绍
笔记·qt·学习
克里斯蒂亚诺更新3 小时前
电脑关闭密码的操作
笔记
小小的代码里面挖呀挖呀挖4 小时前
杰理蓝牙耳机开发--LE Audio与游戏耳机应用
笔记·单片机·物联网·学习
xiaomici4 小时前
SAC中的Dataset/Model/Planning model
笔记
一楼的猫5 小时前
AI写作检测机制技术深度解析:200+维度检测、叙事指纹与网文AI辅助怎么过审
人工智能·学习·安全·chatgpt·ai写作
学数学的口心贝5 小时前
从零搭建并维护个人主页
经验分享·笔记