给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
Sample Input1:
s = "3[a]2[bc]"
Sample Output1:
"aaabcbc"
Sample Input2:
s = "3[a2[c]]"
Sample Output2:
"accaccacc"
分析
此题可以利用递归的思想来做,分为2种情况:
第一种情况是只有字母,字母前无数字,那就直接添加。 如abc,output即直接添加"abc"。
例如:
Sample Input:
s = "abc3[cd]xyz"
Sample Output:
"abccdcdcdxyz"
中的前3个字母以及后3个字母是如何出现在答案中的。
第二种情况是字母前有数字,此时需要递归来解决:
如果遇到 k[***] 的规则,则解析出数字k和字符串***,然后递归解决***是什么,并将解决的结果的在答案中添加k次。
比如***是字母abc,那就将abc在答案中添加3次。
例如:
Sample Input:
s = "abc3[cd]xyz"
Sample Output:
"abccdcdcdxyz"
中cdcdcd是如何出现在答案中的。
如果遇到例如:
Sample Input:
s = "3[a2[c]]"
Sample Output:
"accaccacc"
那就递归着去做:先解决遇到2[c]怎么办,再解决遇到acc怎么办,再解决遇到3[acc]怎么办。
总结
这题是按照深度优先的方式进行遍历,每次遇到一个k规则就会向下递归一层,每做完一个k规则就会回溯一层,k规则的嵌套次数对应了递归的深度,整个遍历顺序对应了一棵深度优先搜索树。
C++代码
class Solution {
public:
string decodeString(string s) {
int u = 0; //用于体现正在解决哪个位置的字符
return dfs(s, u);
}
string dfs(string s, int &u)
{
string res; //用于记录本层的答案
while(u < s.size() && s[u] != ']')
{
//第一种情况如果遇到字母,则直接添加在答案中
if(isalpha(s[u])) res += s[u ++ ];
//第二种情况如果遇到数字,则递归解决
else if(isdigit(s[u]))
{
int cnt = u;
while(isdigit(s[cnt])) cnt ++;
int x = stoi(s.substr(u, u - cnt));
u = cnt + 1;
string tmp = dfs(s, u);
u ++ ;
while(x -- ) res += tmp;
}
}
return res;
}
};
Java代码
class Solution {
int u;//用于体现正在解决哪个位置的字符
String s;
public String decodeString(String _s) {
u = 0;
s = _s;
return dfs();
}
public String dfs() {
String res = "";
while (u < s.length() && s.charAt(u) != ']') {
//第一种情况如果遇到字母,则直接添加在答案中
if (Character.isLetter(s.charAt(u))) {
res += s.charAt(u++);
}
//第二种情况如果遇到数字,则递归解决
else if(Character.isDigit(s.charAt(u))) {
int cnt = u;
while (Character.isDigit(s.charAt(cnt + 1))) cnt++;
int x = Integer.parseInt(s.substring(u, cnt + 1));
u = cnt + 2;
String tmp = dfs();
u++;
while (x > 0) {
res += tmp;
x --;
}
}
}
return res;
}
}