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;
}
相关推荐
hsjiasb19 小时前
FreeRTOS学习(二十七)——任务栈与栈溢出检测
开发语言·stm32·学习·学习笔记·freertos
小弥儿20 小时前
GitHub今日热榜 | 2026-08-16:大模型微调与编码工具扎堆
学习·开源·github
多弗朗皮卡丘20 小时前
C语言梦开始的地方7:函数
c语言·开发语言
2501_9269783321 小时前
AGI 的四种瓶颈:资源型还是发现型--以及DSH的位置
人工智能·经验分享·笔记·ai写作
liuqs3321 天前
nat123安卓和nat123全端口选型指南,映射工具怎么挑
网络·笔记
xian_wwq1 天前
【学习笔记】光伏“四可”装置纵密模块--配置方法和原理
笔记·学习
min(a,b)1 天前
学习第17天:Agent Memory 与 MCP 协议
python·学习
lifallen1 天前
模型不是函数:claude-cookbooks/misc 十四篇的公共底层
人工智能·学习·ai·ai编程
Herbert_hwt1 天前
C语言零基础入门:循环控制与数据类型详解
c语言·数据结构·算法
lucky_syq1 天前
第5篇 · S1·下:前沿架构:MoE、Reasoning 模型、长上下文、多模态、SSM/Mamba 与模型谱系
人工智能·学习·架构