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});

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

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

可以理解成:

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

⑥ 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 是最终结果长度;栈空间复杂度与最大嵌套深度有关。

相关推荐
Nil20819 分钟前
leetcode 118杨辉三角
算法·leetcode·职场和发展
All for pursuit.3 小时前
【设计-1】208.实现Trie (前缀树)
数据结构·c++·算法·leetcode
CoderYanger7 小时前
A.每日一题:1614. 括号的最大嵌套深度
java·程序人生·算法·leetcode·面试·学习方法
Xin7708 小时前
LeetCode 230. 二叉搜索树中第 K 小的元素(迭代中序遍历 + 栈)
leetcode
Navigator_Z8 小时前
LeetCode //C - 1283. Find the Smallest Divisor Given a Threshold
c语言·算法·leetcode
我不会起名字3229 小时前
二叉树的遍历与二叉搜索树:把递归、迭代、还原树一次讲透
数据结构·leetcode·二叉树·二叉搜索树
yi01110 小时前
Leetcode 49 用 “身份证‘‘巧解
人工智能·笔记·python·算法·leetcode·哈希表
yi01110 小时前
DAY22: LeetCode 733:图像渲染——从二维网格开始理解 DFS 和 BFS
数据结构·笔记·python·算法·leetcode·深度优先·宽度优先
Pniubi10 小时前
力扣41缺失的第一个正数(哈希表法)
算法·leetcode·职场和发展
Nil20811 小时前
leetcode 70爬楼梯
算法·leetcode·动态规划