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

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

1. 题目概述

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

  • 输入 :多组测试数据。每组包含一个整数 nnn(序列长度),随后两行分别为 pushed 和 popped 序列。
  • 输出 :如果 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)。虽然代码中有双重循环(for 套 while),但每个元素最多只会被压入栈一次、弹出栈一次。因此总操作次数是线性的。
  • 空间复杂度 :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;
}
相关推荐
个 人 练 习 生1 小时前
C++中的内存管理
开发语言·c++·经验分享·学习
AI+程序员在路上1 小时前
AP6275S蓝牙双接口解析:HCI UART与PCM的分工与协同
linux·c语言·物联网
江湖人称菠萝包1 小时前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter11-数据库
笔记·qt·qt5
jingli92 小时前
本地向量库索引把 C 盘塞爆 48.6G:一次 LanceDB 膨胀排查与根治实录
c语言·开发语言
浩瀚地学2 小时前
deepagents学习打卡day08
经验分享·笔记·python·学习·agent
艾莉丝努力练剑2 小时前
【AI大模型接入SDK】ChatSDK整体实现
网络·c++·人工智能·学习·架构
励志不掉头发的内向程序员2 小时前
【从零写一个CAD 02】画完第一条线之后:实体容器、Esc 取消,和按了没反应的键盘
开发语言·c++·qt·学习·系统架构
摇滚侠2 小时前
《On Java 中文版 基础卷》阅读笔记 安装 Java 和本书示例 02
java·开发语言·笔记
阿钱真强道2 小时前
21 嵌入式操作系统 | JSON 与 json-c:生成与解析
c语言·开发语言·json·json-c
艾莉丝努力练剑2 小时前
【AI大模型接入SDK】ChatSDK架构设计与实现
网络·c++·人工智能·学习·语言模型