Decode String

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;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值