【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;
    }
};
相关推荐
Tisfy几秒前
LeetCode 2540.最小公共值:双指针(O(m+n))
算法·leetcode·题解·双指针
IronMurphy6 分钟前
【算法四十七】152. 乘积最大子数组
算法
REDcker8 分钟前
有限状态机与状态模式详解 FSM建模Java状态模式与C++表驱动模板实践
java·c++·状态模式
basketball6161 小时前
C++ 构造函数完全指南:从入门到进阶
java·开发语言·c++
淘矿人1 小时前
Claude辅助DevOps实践
java·大数据·运维·人工智能·算法·bug·devops
Cosolar1 小时前
万字详解:RAG 向量索引算法与向量数据库架构及实战
数据库·人工智能·算法·数据库架构·milvus
想唱rap2 小时前
IO多路转接之poll
服务器·开发语言·数据库·c++
落羽的落羽3 小时前
【算法札记】练习 | Week4
linux·服务器·数据结构·c++·人工智能·算法·动态规划
goodesocket3 小时前
芯片HAST测试:通电工作下如何精准模拟极端环境挑战?
c++