题目描述
给定一个经过编码的字符串,返回它解码后的结果。编码规则是:
k[encoded_string],表示 encoded_string 在方括号内的部分正好重复 k 次。
例如:
输入: s = "3[a2[c]]"
输出: "accaccacc"
思路分析
整道题的关键在于:
遇到 **]**就说明要"展开"最近的一段编码。
而要展开一段编码,必须知道两部分内容:
-
括号里的字符串(例如
abc) -
前面的数字(例如
3)
由于字符串中可能有嵌套(例如 3[a2[c]]),普通的线性扫描难以处理"内层先展开"的逻辑。
因此我们使用 栈(stack) 来模拟整个过程。
栈的思路拆解
-
遍历字符串:
-
如果当前字符不是
],直接压栈; -
如果遇到
],说明我们找到了一段完整的结构,需要出栈处理。
-
-
当遇到 **]**时:
-
从栈顶依次弹出字符,直到遇到
'['; -
这部分拼出的字符串就是当前要重复的内容。
-
-
取出数字部分:
-
'['前面紧挨着的可能是一串数字(比如10[ab]); -
从栈顶继续弹出所有数字并拼接;
-
将其转为整数
k。
-
-
重复并压回:
-
把刚刚取出的字符串重复
k次; -
再把展开结果一个字符一个字符地压回栈中。
-
-
最后:
- 栈中剩下的就是完全展开的结果,从底到顶拼起来即可。
代码实现
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)(使用了辅助栈)。
总结
这题的精髓在于:
用栈"模拟"了递归调用展开的过程。
你可以记住一个通用模板:
"括号匹配 + 层级展开"类问题(如算式计算、字符串解码)几乎都可以用栈解决。