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 相同。