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

题目描述

给定一个经过编码的字符串,返回它解码后的结果。编码规则是:
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)(使用了辅助栈)。

总结

这题的精髓在于:

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

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

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

相关推荐
Re_zero19 小时前
线上日志被清空?这段仅10行的 IO 代码里竟然藏着3个毒瘤
java·后端
洋洋技术笔记19 小时前
Spring Boot条件注解详解
java·spring boot
程序员清风2 天前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林5512 天前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
华仔啊2 天前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing2 天前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠2 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840823 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide3 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家3 天前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java