leetcode 394字符串解码

这道 字符串解码 decodeString 的重点就是:用栈保存进入 [ 之前的状态,遇到 ] 再恢复状态并完成字符串展开。

代码总结

复制代码
class Solution {
public:
    string decodeString(string s) {
        int time = 0;              // 当前重复次数
        string result = "";        // 当前层得到的字符串
        stack<pair<int,string>> st; // 保存 <倍数, 上一层字符串>

        for (auto c : s) {

            // 1. 数字:计算重复次数,支持多位数
            if (isdigit(c)) {
                time = time * 10 + (c - '0');
            }

            // 2. 字母:加入当前字符串
            if (isalpha(c)) {
                result += c;
            }

            // 3. 遇到 '[':保存当前状态,进入下一层
            if (c == '[') {
                st.push({time, result});

                time = 0;
                result = "";
            }

            // 4. 遇到 ']':恢复上一层状态
            else if (c == ']') {
                auto [lasttime, laststr] = st.top();
                st.pop();

                // 当前字符串重复 lasttime 次
                string temp = "";
                for (int i = 0; i < lasttime; i++) {
                    temp += result;
                }

                // 与上一层字符串进行拼接
                result = laststr + temp;
            }
        }

        return result;
    }
};

核心流程可以直接记成:

复制代码
数字 → 计算 time

字母 → result += c

遇到 [
    ↓
把 {time, result} 压栈
    ↓
time = 0
result = ""
    ↓
开始处理括号内部

遇到 ]
    ↓
取出上一层 {lasttime, laststr}
    ↓
当前 result 重复 lasttime 次
    ↓
result = laststr + 重复后的字符串

例如:

复制代码
3[a2[c]]

3[       → 保存 <3, "">
a2[      → 保存 <2, "a">
c]       → "c" × 2 → "a" + "cc" = "acc"
]        → "acc" × 3

最终:
"accaccacc"

你这次写代码出现的易错点

time 一定初始化为 0

你最开始写过:

复制代码
int time;       // ❌

应该:

复制代码
int time = 0;   // ✅

因为后面马上使用:

复制代码
time = time * 10 + (c - '0');

如果没有初始化,time 的初始值是不确定的。


② 多位数字不能只写 c - '0'

错误理解:

复制代码
time = c - '0';

只能处理:

复制代码
3[a]

不能正确处理:

复制代码
12[a]

所以应该:

复制代码
time = time * 10 + (c - '0');

例如:

复制代码
读到 1:

0 × 10 + 1 = 1

读到 2:

1 × 10 + 2 = 12

记住这个常用公式:

复制代码
num = num * 10 + 当前数字;

stack<pair<int,string>> 压入的是一个 pair

你之前写过:

复制代码
st.push(time, result);        // ❌

但栈的一个元素是:

复制代码
pair<int,string>

所以应该:

复制代码
st.push({time, result});      // ✅

也可以:

复制代码
st.emplace(time, result);     // ✅

result = ""result = " " 不一样

你之前写过:

复制代码
result = " ";    // ❌

这是一个真正的空格字符

应该:

复制代码
result = "";     // ✅

区别:

复制代码
""   → 空字符串
" "  → 包含一个空格

⑤ 遇到 [ 后必须清空当前状态

复制代码
st.push({time, result});

time = 0;
result = "";

因为:

复制代码
st.push({time, result});

已经把上一层状态保存好了

清空之后,timeresult 才能专门处理括号里面的新一层。

可以理解成:

复制代码
保存上一层
   ↓
清空
   ↓
处理下一层
   ↓
遇到 ]
   ↓
恢复上一层

st.top() 返回的是一个 pair

你之前写过类似:

复制代码
auto lasttime, laststr = st.top();   // ❌

正确:

复制代码
auto [lasttime, laststr] = st.top(); // ✅

这是 C++17 的结构化绑定

如果栈顶:

复制代码
<3, "abc">

那么:

复制代码
auto [lasttime, laststr] = st.top();

相当于:

复制代码
lasttime = 3
laststr  = "abc"

也就是:

复制代码
pair.first  → lasttime
pair.second → laststr

] 时使用的是 lasttime,不是 time

你之前这里写错过:

复制代码
for (int i = 0; i < time; i++) {     // ❌
    temp += result;
}

应该:

复制代码
for (int i = 0; i < lasttime; i++) { // ✅
    temp += result;
}

因为遇到 [ 时:

复制代码
st.push({time, result});
time = 0;

原来的倍数已经被保存到栈里了。

遇到 ]

复制代码
auto [lasttime, laststr] = st.top();

才把原来的倍数取回来。


最后把这题压缩成一句最值得记的:

数字算倍数,字母直接拼;[ 保存现场并清空,] 恢复现场并重复拼接。

时间复杂度主要取决于最终解码字符串的长度,可以理解为 O(n+L)O(n + L),其中 LL 是最终结果长度;栈空间复杂度与最大嵌套深度有关。

相关推荐
一起努力啊~4 小时前
算法题打卡力扣第1658题:将 x 减到 0 的最小操作数(mid)
学习·leetcode
Cccp.1235 小时前
【leetcode】(六) 图和贪心算法
数据结构·算法·leetcode
y1su5 小时前
【Leetcode】1477. 找两个和为目标值且不重叠的子数组
数据结构·后端·算法·leetcode·职场和发展
mmmmath_316 小时前
LeetCode.541.反转字符串II
数据结构·算法·leetcode
Navigator_Z16 小时前
LeetCode //MySQL - 1251. Average Selling Price
c语言·算法·leetcode
参.商.17 小时前
【Day 53】76. 最小覆盖子串
leetcode·golang
虚无的纽扣20 小时前
【力扣刷题】第二天:无重复字符的最长字串、移动零问题
算法·leetcode·排序算法
圣保罗的大教堂1 天前
leetcode 3742. 网格中得分最大的路径 中等
leetcode
我不会起名字3221 天前
一天一道算法题(35):电话号码的字母组合
java·数据结构·后端·python·leetcode·go·回溯