1. 解析
题目大意,对字符串进行解码,前面的数字是中括号[ ]中字符串出现的次数
2. 分析
这种结构就是嵌套结构,一般解析嵌套结构的字符串,都需要用到栈,或者用递归求解,不过我个人认为迭代的方式求解更简单一点,因为递归有时候不是很好调试。我处理的方式复杂一点,我用pair键值对保存后面中括号中字符串出现的次数和对应的字符串,例如3[abc],pair对即为[3, "abc"],也可以利用双栈分开保存。整个字符串只由4种字符组成:数字、字母(包括大写字母,刚开始我就忽略这一点)、'['、']',如果检测到当前位置是数字,一直往下检索直到不是数字,题目已经明确,数字的下一个状态即为'[',所以我们检测到'['时,前面的字符就是出现的次数,接着检测中括号中的字母,若碰到非字母,保存下当前的字符串,当检测到']',说明当前'['所存储在栈中的字符串已经解析完,连接到上一个状态所解析出的字符串后面即可。文字描述不是很清楚,详见代码。
class Solution {
public:
string decodeString(string s) {
stack<pair<int, string>> num_to_str;
int start = 0;
string res = ""; //存放最终的结果
for (int i = 0; i < s.length(); ++i){
if (s[i] != ']' && s[i] != '[' && !('0'<= s[i] && s[i] <= '9')){ //字母
if (num_to_str.empty()) res += s[i];
else num_to_str.top().second += s[i];
}
else if (s[i] == '['){
int num = atoi(s.substr(start, i-start).c_str());
int j = ++i;
while (s[i] != ']' && !('0'<= s[i] && s[i] <= '9')) ++i; //中括号里面的字母
num_to_str.push({num, s.substr(j, i - j)});
i--; //回溯到上一个位置,不然会跳过当前字符,需要注意
}
else if (s[i] == ']'){
pair<int, string> cur = num_to_str.top();
num_to_str.pop();
if (num_to_str.size() >= 1){ //存在上一个未解析完的状态,先解析
for (int j = 0; j < cur.first; ++j)
num_to_str.top().second += cur.second;
}
else{
for (int j = 0; j < cur.first; ++j)
res += cur.second;
}
}
else{ //数字
start = i;
while ('0' <= s[i] && s[i] <= '9') i++;
i--; //回溯到上一个位置,不然会跳过当前字符,需要注意
}
}
return res;
}
};
3. 精简的解法
参考@Grandyang的解法,他采用了双栈结构解析,一个栈保存次数,一个栈保存字符串。解法比较好的一点就是,当前状态的字符串用res变量保存,详见代码。
例如: 3[ab2[c]]ed,栈中存储的状态依次变化如下
'3',cnt = 3
'[',cnt = 3,nums = [ 3 ],str = [ "" ]
'a',cnt = 0,nums = [ 3 ],str = [ "" ],res = "a"
'b',cnt = 0,nums = [ 3 ],str = [ "" ],res = "ab"
'2',cnt = 2,nums = [ 3 ],str = [ "" ],res = "ab"
'[',cnt = 2,nums = [ 3, 2 ],str = [ "", "ab" ],res = "" //检测到新的一层
'c',cnt = 0,nums = [ 3, 2 ],str = [ "", "ab" ],res = "c"
']',cnt = 0,nums = [ 3, 2 ],str = [ "" ],res = "abccc" 结束当前层的解析
.......
从以上可以看出,res保存的字符是当前层的字符,nums保存的就是当前层字符串的出现的次数,str保存当前层的字符串,我们只需依次出栈即可
class Solution {
public:
string decodeString(string s){
stack<int> nums;
stack<string> str;
string res = "";
int cnt = 0;
for (char ch: s){
if ('0' <= ch && ch <= '9'){ //数字
cnt = cnt * 10 + (ch - '0');
}
else if (ch == '['){ //检测到下一层节点
nums.push(cnt);
str.push(res);
cnt = 0;
res = "";
}
else if (ch == ']'){ //当前层结束
int num = nums.top();
nums.pop();
while (num-- > 0)
str.top() += res;
res = str.top();
str.pop();
}
else{
res += ch;
}
}
return res;
}
};