【Hot 100 刷题计划】 LeetCode 394. 字符串解码 | C++ 单栈回压法

LeetCode 394. 字符串解码

📌 题目描述

题目级别:中等

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

  • 示例 1:

    输入:s = "3[a]2[bc]"

    输出:"aaabcbc"

  • 示例 2:

    输入:s = "3[a2[c]]"

    输出:"accaccacc"


💡 破题思路:单栈回压法 (Single Stack Re-push)

绝大多数教程在讲这道题时,都会教你使用"双栈法"(一个栈存数字,一个栈存字符串)。

但实际上,仅用一个字符栈也能极其优雅地解决问题,并且逻辑更加贴近底层硬件的工作方式。

本解法完美处理了两个最大痛点:

  1. 多位数字还原 :当遇到 ] 弹栈找数字时,数字是倒着出来的(比如 100,先弹出 0,再弹出 0,最后弹出 1)。我们利用权重变量 w(初始为 1,每次乘 10),通过 k = (st.top() - '0') * w + k 完美还原真实数值。
  2. 嵌套括号问题 (核心魔法) :当遇到 3[a2[c]] 这种嵌套结构时,我们在内部遇到第一个 ],解出了 cc。此时千万不能 把它直接加到最终结果里!我们的做法是:把它打散成字符,重新 push 回栈里! 这样一来,cc 就变成了普通的字符,和外层的 a 紧紧挨在了一起,静静等待外层括号的下一次结算。这就叫"回压法"。

💻 C++ 代码实现 (单栈极客版)

cpp 复制代码
class Solution {
public:
    string decodeString(string s) {
        int n = s.size();
        stack<char> st; // 全局仅需一个字符栈
        string res;

        for (int i = 0; i < n; i ++ )
        {
            if (s[i] != ']')
            {
                // 不是右括号,统统入栈保存现场
                st.push(s[i]);
            }
            else 
            {
                // 遇到右括号,开始清算当前这一层!
                string tmp;

                // 1. 弹出中括号内的纯字母字符串
                while (st.top() != '[')
                {
                    // 注意拼接顺序,栈是先进后出的,所以要加在前面
                    tmp = st.top() + tmp;
                    st.pop();
                }
                st.pop(); // 弹出 '['

                // 2. 弹出前面的数字 (支持多位数字解析)
                int k = 0, w = 1;
                while (!st.empty() && st.top() >= '0' && st.top() <= '9')
                {
                    k = (st.top() - '0') * w + k;
                    w *= 10;
                    st.pop(); 
                }

                // 3. 将字符串按照解析出的数字倍数进行放大
                string add;
                for (int j = 0; j < k; j ++ ) 
                {
                    add += tmp;
                }
                
                // 4. 终极魔法:将放大后的字符串重新逐个压回栈中!
                // 完美化解嵌套危机,让它们参与外层括号的下一次清算
                for (int j = 0; j < add.size(); j ++ )
                {
                    st.push(add[j]);
                }
            }
        }

        // 大循环结束后,栈里剩下的就是完全解码的字符了
        while (st.size())
        {
            res = st.top() + res;
            st.pop();
        }

        return res;
    }
};
相关推荐
穿条秋裤到处跑2 小时前
每日一道leetcode(2026.04.22):距离字典两次编辑以内的单词
算法·leetcode
淘矿人2 小时前
Claude辅助算法设计与优化
人工智能·python·算法·microsoft·github·bug·pygame
流年如夢2 小时前
自定义类型进阶:联合与枚举
java·c语言·开发语言·数据结构·数据库·c++·算法
wayz112 小时前
Day 10:集成学习进阶(Boosting: AdaBoost, GBDT)
算法·机器学习·集成学习·boosting
Little At Air2 小时前
C++stack模拟实现
linux·开发语言·c++·算法
张祥6422889042 小时前
导数与微分有啥区别
算法·数学建模
rayyy92 小时前
c++, sizeof(string)和string.size()有什么区别
c++
葳_人生_蕤2 小时前
hot100——图
数据结构·算法
Rust研习社3 小时前
深入浅出 Rust 泛型:从入门到实战
开发语言·后端·算法·rust