给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为:k[encoded_string]
,表示其中方括号内部的encoded_string
正好重复k
次。注意k
保证为正整数。
你可以认为输入字符串总是有效的;输入字符串没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数k
,例如不会出现像3a
或2[4]
的输入。
示例1:
输入:s = “3[a]2[bc]”
输出:“aaabcbc”
示例2:
输入:s = “3[a2[c]]”
输出:“accaccacc”
思路:
输入的字符串可能存在括号嵌套的情况,此时我们都是先对内部括号中的字符串进行解码,然后再依次对外部括号内的字符串进行解码,也就是说我们从左到右遍历字符串时,先遍历到的[
内部的字符串会后进行解码,这符合栈先进后出的特点,因此该问题我们可以借助栈来进行求解。
对输入的字符串进行遍历,遍历时的做法如下:
- 遍历到的是数字,先将完整的数字字符串提取出来,然后进行压栈。
- 遍历到的是字母或
'['
,直接将其进行压栈。 - 遍历到的是
']'
,先获取到待复制的字符串,再将其进行复制,最好将复制后的字符串重新进行压栈。
当遍历到']'
时,具体操作步骤如下:
- 先进行弹栈,将弹出的字符串保存到vector当中,直到’[‘被弹出时停止弹栈,’['不保存到vector中。
- 再将vector当中的内容进行逆置,因为出栈的顺序与入栈顺序相反。
- 然后将待复制的若干字符串进行拼接,得到最终待复制的字符串。
- 弹出此时栈顶的数字字符串,并将其转换成整数num。
- 将待复制的字符串复制num次,最终得到复制后的字符串。
- 将复制后的字符串进行压栈。
最终当输入的字符串遍历完毕时,将栈中的字符串拼接后即为最终解码后的字符串。代码如下:
class Solution {
public:
//从字符串s的pos位置开始,提取数字字符串
string GetNum(string& s, size_t& pos)
{
string num;
while (s[pos] != '[')
{
num += s[pos];
pos++;
}
return num;
}
//将vector当中的字符串拼接后进行返回
string GetString(vector<string>& st)
{
string s;
for (auto e : st)
{
s += e;
}
return s;
}
string decodeString(string s) {
vector<string> st; //数组模拟栈
size_t pos = 0; //用于遍历字符串s
while (pos < s.size())
{
//1、遍历到的是数字,先将完整的数字字符串提取出来,然后进行压栈
if (isdigit(s[pos]))
{
string num = GetNum(s, pos);
st.push_back(num);
}
//2、遍历到的是字母或'[',直接将其进行压栈
else if (isalpha(s[pos]) || s[pos] == '[')
{
st.push_back(string(1, s[pos]));
pos++;
}
//3、遍历到的是']',先获取到待复制的字符串,再将其进行复制,最好将复制后的字符串重新进行压栈
else
{
vector<string> sub; //待复制的若干字符串
//a、先进行弹栈,将弹出的字符串保存到vector当中,直到'['被弹出时停止弹栈,'['不保存到vector中
while (st.back() != "[")
{
sub.push_back(st.back());
st.pop_back();
}
st.pop_back();
//b、再将vector当中的内容进行逆置,因为出栈的顺序与入栈顺序相反
reverse(sub.begin(), sub.end());
//c、然后将待复制的若干字符串进行拼接,得到最终待复制的字符串
string all = GetString(sub);
//d、弹出此时栈顶的数字字符串,并将其转换成整数num
int num = stoi(st.back());
st.pop_back();
//d、将待复制的字符串复制num次,最终得到复制后的字符串
string str; //复制后的字符串
while (num--)
{
str += all;
}
//e、将复制后的字符串进行压栈
st.push_back(str);
pos++;
}
}
return GetString(st); //将栈当中的字符串拼接后进行返回
}
};
代码说明:
- 代码当中并没有使用真正的stack,而是用vector模拟实现的压栈和出栈,是为了方便从栈底向栈顶进行遍历。(这点很重要)
- GetNum函数的参数pos需要使用引用传参,保证我们一直使用的都是同一个pos变量在对字符串进行遍历。