从零开始刷算法-栈-字符串解码

题目描述

给定一个经过编码的字符串,返回它解码后的结果。编码规则是:
k[encoded_string],表示 encoded_string 在方括号内的部分正好重复 k 次。

例如:

复制代码
输入: s = "3[a2[c]]"
输出: "accaccacc"

思路分析

整道题的关键在于:

遇到 **]**就说明要"展开"最近的一段编码。

而要展开一段编码,必须知道两部分内容:

  1. 括号里的字符串(例如 abc)

  2. 前面的数字(例如 3)

由于字符串中可能有嵌套(例如 3[a2[c]]),普通的线性扫描难以处理"内层先展开"的逻辑。

因此我们使用 栈(stack) 来模拟整个过程。

栈的思路拆解

  1. 遍历字符串:

    • 如果当前字符不是 ],直接压栈;

    • 如果遇到 ],说明我们找到了一段完整的结构,需要出栈处理。

  2. 当遇到 **]**时:

    • 从栈顶依次弹出字符,直到遇到 '[';

    • 这部分拼出的字符串就是当前要重复的内容。

  3. 取出数字部分:

    • '[' 前面紧挨着的可能是一串数字(比如 10[ab]);

    • 从栈顶继续弹出所有数字并拼接;

    • 将其转为整数 k。

  4. 重复并压回:

    • 把刚刚取出的字符串重复 k 次;

    • 再把展开结果一个字符一个字符地压回栈中。

  5. 最后:

    • 栈中剩下的就是完全展开的结果,从底到顶拼起来即可。

代码实现

复制代码
class Solution {
public:
    string decodeString(string s) {
        stack<char> st;
        for (char c : s) {
            if (c != ']') {
                // 左括号或普通字符都压栈
                st.push(c);
            } else {
                // 1️⃣ 取出当前方括号内的内容
                string cur;
                while (!st.empty() && st.top() != '[') {
                    cur = st.top() + cur;
                    st.pop();
                }
                st.pop(); // 弹出 '['

                // 2️⃣ 取出重复次数
                string num;
                while (!st.empty() && isdigit(st.top())) {
                    num = st.top() + num;
                    st.pop();
                }
                int k = stoi(num);

                // 3️⃣ 构造展开字符串
                string repeated;
                for (int i = 0; i < k; i++) repeated += cur;

                // 4️⃣ 压回栈中
                for (char ch : repeated) st.push(ch);
            }
        }

        // 5️⃣ 拼接最终结果
        string ans;
        while (!st.empty()) {
            ans = st.top() + ans;
            st.pop();
        }
        return ans;
    }
};

示例演示:3[a2[c]]

步骤 栈内容 说明
读到 '3' 3 压栈
读到 '[' 3 [ 压栈
读到 'a' 3 [ a 压栈
读到 '2' 3 [ a 2 压栈
读到 '[' 3 [ a 2 [ 压栈
读到 'c' 3 [ a 2 [ c 压栈
读到 ']' 3 [ a cc 展开内层得到 "cc"
继续 ']' accaccacc 展开外层得到 "accaccacc"

时间复杂度分析

  • 每个字符最多进栈出栈一次,因此时间复杂度为 O(n)。

  • 空间复杂度为 O(n)(使用了辅助栈)。

总结

这题的精髓在于:

用栈"模拟"了递归调用展开的过程。

你可以记住一个通用模板:

"括号匹配 + 层级展开"类问题(如算式计算、字符串解码)几乎都可以用栈解决。

相关推荐
九皇叔叔4 分钟前
【09】SpringBoot4 MyBatisPlus 增删改查(CRUD)
java·mybatis·mybatisplus
凉茶钱11 分钟前
【吃透C++】万字解析类和对象
开发语言·c++
白杨尚青34 分钟前
C++入门篇(十):string(上)——认识string:构造与三大遍历(一条龙讲透operator[]、迭代器、auto、范围for)
java·开发语言·c++·笔记·stl
可乐鸡翅yeah_39 分钟前
hls.js 切换多个视频源,新手开发常见踩坑
开发语言·前端·javascript·ios·ffmpeg·音视频·safari
Tanshu_API君42 分钟前
API 聚合平台选型指南:从参数拆解到生产落地的十个评估维度
开发语言·api
Chen—LSN43 分钟前
C语言——⽂件操作(1)
c语言·开发语言·c++·经验分享·笔记·算法·链表
狗凯之家源码网1 小时前
PHP 开源 IM 即时通讯系统效果实测与功能展示
开发语言·开源·php
anew___1 小时前
《从零手写操作系统 (11):文件系统初探——initrd与VFS抽象层》
java·javascript·算法
天天向上2911 小时前
Spring AI 实战:14 个踩坑记录,其中一个让我的测试全绿但产品是坏的
java·开源
正在走向自律1 小时前
从只写接口到独立交付前后端,飞算JavaAI能给Java后端工程师多少溢价?
java·springboot·ai编程·全栈开发·java求职·飞算javaai·金九银十