Leetcode394. 字符串解码

本文介绍了一种使用栈的方法解决LeetCode题目394——字符串解码,通过处理括号嵌套和数字字符,利用栈存储TOKEN,最终将解码后的字符串逆序拼接。时间复杂度和空间复杂度均为O(S)。

Every day a Leetcode

题目来源:394. 字符串解码

解法1:栈

本题中可能出现括号嵌套的情况,比如 2[a2[bc]],这种情况下我们可以先转化成 2[abcbc],在转化成 abcbcabcbc。我们可以把字母、数字和括号看成是独立的 TOKEN,并用栈来维护这些 TOKEN。

具体的做法是,初始化一个栈 stk = stack<string>,遍历字符串 s,设当前字符为 cur = s[i]:

  • 如果 cur 是一个数字字符:设置一个字符串 num,从当前下标 i 开始,一直遍历下去直到 i 不是数字字符,不断加入 num 中。最后将 num 压入栈中。
  • 如果 cur 是一个英文字母:将该字符转换成字符串后压入栈中。
  • 如果 cur 是 ‘[’:将该字符转换成字符串后压入栈中。
  • 否则,cur 是 ‘]’:新建一个字符串数组 sub,不断将栈顶元素弹出直到栈顶元素是 “[”,并插入到 sub 数组里。此时栈顶元素是 “[”,这个没有用,弹出,然后新的栈顶就是一个数字字符串 num,转为 int,这个就是要重复的次数,记为 repeatTime,再将栈顶弹出。由于栈的特性,数组 sub 中字符的顺序是倒置的,我们先 reverse(sub.begin(), sub.end()),再用字符串 temp 将 sub 中的字符串累加起来,最后将 temp 重复 repeatTime 次,最终得到的字符串压入栈顶。

最后,将栈中的所有字符串累加起来,再次由于栈的特性,逆序才是正确答案。我们也可以用 insert 来将栈顶字符串插入到答案的开头来做:

string ans = "";
while (!stk.empty())
{
	ans.insert(0, stk.top());
	stk.pop();
}
return ans;

代码:

/*
 * @lc app=leetcode.cn id=394 lang=cpp
 *
 * [394] 字符串解码
 */

// @lc code=start
class Solution
{
public:
    string decodeString(string s)
    {
        int n = s.size(), i = 0;
        stack<string> stk;
        while (i < n)
        {
            char cur = s[i];
            if (isdigit(cur))
            {
                string num = "";
                while (isdigit(s[i]))
                {
                    num.push_back(s[i]);
                    i++;
                }
                stk.push(num);
            }
            else if (isalpha(cur) || cur == '[')
            {
                stk.push(string(1, s[i]));
                i++;
            }
            else // cur == ']'
            {
                vector<string> sub;
                while (stk.top() != "[")
                {
                    sub.push_back(stk.top());
                    stk.pop();
                }
                reverse(sub.begin(), sub.end());
                stk.pop(); // 左括号出栈
                // 此时栈顶为当前 sub 对应的字符串应该出现的次数
                int repeatTime = stoi(stk.top());
                stk.pop();
                string temp = "";
                while (repeatTime--)
                {
                    for (string &str : sub)
                        temp += str;
                }
                stk.push(temp);
                i++;
            }
        }
        string ans = "";
        while (!stk.empty())
        {
            ans.insert(0, stk.top());
            stk.pop();
        }
        return ans;
    }
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(S),其中 S 是解码后得出的字符串长度。除了遍历一次原字符串 s,我们还需要将解码后的字符串中的每个字符都入栈,并最终拼接进答案中,故渐进时间复杂度为 O(S+∣s∣),即 O(S)。

空间复杂度:O(S),其中 S 是解码后得出的字符串长度。这里用栈维护 TOKEN,栈的总大小最终与 S 相同。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值