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)
绝大多数教程在讲这道题时,都会教你使用"双栈法"(一个栈存数字,一个栈存字符串)。
但实际上,仅用一个字符栈也能极其优雅地解决问题,并且逻辑更加贴近底层硬件的工作方式。
本解法完美处理了两个最大痛点:
- 多位数字还原 :当遇到
]弹栈找数字时,数字是倒着出来的(比如100,先弹出0,再弹出0,最后弹出1)。我们利用权重变量w(初始为 1,每次乘 10),通过k = (st.top() - '0') * w + k完美还原真实数值。 - 嵌套括号问题 (核心魔法) :当遇到
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;
}
};