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

题目描述

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

总结

这题的精髓在于:

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

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

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

相关推荐
你不是我我2 小时前
【Java 开发日记】设计模式了解吗,知道什么是饿汉式和懒汉式吗?
android·java·开发语言
2501_929177582 小时前
C++中的虚基类
开发语言·c++·算法
♡喜欢做梦2 小时前
Spring MVC 响应处理:页面、数据与状态配置详解
java·javascript·spring·java-ee
计算机学姐2 小时前
基于SpringBoot的公务员考试管理系统【题库组卷+考试练习】
java·vue.js·spring boot·后端·java-ee·intellij-idea·mybatis
chenbin___2 小时前
Omit<>的用法
开发语言·前端·javascript
HahaGiver6662 小时前
Unity与Android原生交互开发入门篇 - 打开Android的设置
android·java·unity·游戏引擎·android studio
Blossom.1182 小时前
把AI“贴”进路灯柱:1KB决策树让老旧路灯自己报「灯头松动」
java·人工智能·python·深度学习·算法·决策树·机器学习
QT 小鲜肉3 小时前
【QT/C++】Qt网络编程进阶:TCP网络编程的基本原理和实际应用(超详细)
c语言·开发语言·网络·c++·qt·学习·tcp/ip
C# 学习者3 小时前
C# 为异步函数实现WaitAsync方法
java·前端·c#