Given an encoded string, return it's decoded string.
The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.
You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.
Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or 2[4].
Examples:
s = "3[a]2[bc]", return "aaabcbc".
s = "3[a2[c]]", return "accaccacc".
s = "2[abc]3[cd]ef", return "abcabccdcdcdef".
这种大括号套小括号的问题,递归肯定是值得考虑的方向,毕竟嵌套结构下都是性质相同的问题。
方法一:递归
首先要明确,递归的层次,每一对括号是一个递归层,在这一层里,我们用一个string储存字符,同时记录这一层的重复次数,也就是数字大小,注意这里的数字可能是多位。然后进入这一层是从左括号开始,返回是在遇到右括号的时候。具体代码如下:
string helper(string s, int &k)
{
string res = "";
int count = 0;
while (k < s.size()) {
if (isdigit(s[k])) count = count * 10 + (s[k++] - '0');
else if (s[k] == '[') {
string temp = helper(s, ++k);
for (int i = 0; i < count; i++) res += temp;
count = 0;//注意这里的归零,否则后面的统计会出错。
}
else if (s[k] == ']') {
k++;
return res;
}
else res += s[k++];
}
return res;
}
string decodeString(string s) {
int k = 0;
return helper(s, k);
}
这一题用递归比较好理解,如果不用递归也是可以的,可以用栈来操作。
方法二:栈
这个和递归的过程很像,栈里保存上一层的数据,遇到左括号开始存储新的一层的res,遇到右括号,开始弹出上一层的数据,然后按照count的次数把这一层的数据重复几次接到上一层的数据后,遇到新的左括号再把这个数据存到栈里。
string decodeString(string s) {
stack<int> counts;
stack<string> strs;
string res = "";
int i = 0, num = 0;
while (i < s.size()) {
if (s[i] >= '0' && s[i] <= '9') {
num = 0;
while (s[i] >= '0' && s[i] <= '9') {
num = num * 10 + (s[i] - '0');
i++;
}
counts.push(num);//用栈来存储每一层的重复次数
}
else if (s[i] == '[') {
strs.push(res);
res = "";//左括号代表开启新的一层,res归零
i++;
}
else if (s[i] == ']') {
string laststr = strs.top();
strs.pop();//弹出上一层的数据
int cnnum = counts.top();
counts.pop();
for (int j = 0; j < cnnum; j++) {
laststr += res;
}
res = laststr;
i++;
}
else {
res += s[i];
i++;
}
}
return res;
}
其实这个栈的实现就是在模拟递归的过程,而递归本质也是在使用内部的递归栈存储数据,所以原理上是相通的,大家对照理解。