394. 字符串解码

 

 

 

class Solution {
    public String decodeString(String s) {
        int k = 0;
        StringBuilder res = new StringBuilder();
        Stack<Integer> kstack = new Stack<>();
        Stack<StringBuilder> restack = new Stack<>();
        
        for(char c : s.toCharArray()){
            if(c == '['){
                //碰到括号,记录K和当前res,归零。
                kstack.push(k);
                restack.push(res);
                k = 0;
                res = new StringBuilder(); 
            }else if(c ==']'){
                //出最近的一个左括号入的k,当前res进行计算不入栈
                int curk = kstack.pop();
                StringBuilder temp = new StringBuilder();
                for(int i = 0; i < curk; i++){
                    temp.append(res);
                }
                //与括号外合并
                res = restack.pop().append(temp);
                
            }else if(c >= '0' && c <= '9'){
                k = c - '0' + k * 10;
                //如果k是多位数需要x10
            }else{
                res.append(c);
                //如果是字母则缓慢添加
            }
        }
        return res.toString();
        
        
    }
}

力扣

public String decodeString(String s) {
        // 思路: 乘法和 递推公式 前一个和作为下一个加法的加数
        // 3[a]2[bc] = 3a+2bc = (3a + "") + 2bc
        // 3[a2[c]] = 3(2c + a) = 3(2c + a) + ""
        
        // 1. 初始化倍数和res 及其对应栈
        int multi = 0;
        StringBuilder res = new StringBuilder();
        Deque<Integer> multi_stack = new LinkedList<>();
        Deque<String> res_stack = new LinkedList<>();

        // 2. 遍历字符
        char[] chars = s.toCharArray();
        for (char ch : chars) {
            // 3. 统计倍数
            if (ch >= '0' && ch <= '9')
                multi = multi * 10 + (ch - '0');
            // 4. 统计res
            else if (ch >= 'a' && ch <= 'z') 
                res.append(ch);
            // 5. 入栈并重置临时变量
            else if (ch == '[') {
                multi_stack.push(multi);
                res_stack.push(res.toString());
                // 重置开始下一轮重新统计
                multi = 0;
                res = new StringBuilder();
            // 6. 出栈做字符串乘法和加法
            } else {
                int cur_multi = multi_stack.pop();
                StringBuilder temp = new StringBuilder();
                // 乘以当前统计字符串res
                for (int i = 0; i < cur_multi; i++)
                    temp.append(res);
                // 加上前一个统计字符串作为当前res
                res = new StringBuilder(res_stack.pop() + temp);
            }
        }
        return res.toString();
    }

C++ 

  string decodeString(string s) {
	//两个栈分别压int res和用pair
	stack<pair<int, string>> sta;
	int num = 0; string res = "";
	//循环检查字符串
	for (int i = 0; i < s.size(); i++) {
		//遇到数字则存入num
		if (s[i] >= '0'&&s[i] <= '9') {
			num *= 10;//num=num*10
			num += (s[i] - '0');//这里括号是否需要
		}
		else if (s[i] == '[') {//遇到[压栈数字和字符串,置零置空
			sta.push(make_pair(num, res));
			num = 0;
			res = "";
		}
		else if (s[i] == ']') {//遇到]出栈数字和字符串,组装
			int n = sta.top().first;//n指示的是res的循环次数,不是a的
			string a = sta.top().second;
			sta.pop();
			for (int i = 0; i < n; i++)  a = a + res; //循环n次
			res = a;
		}
		else {//遇到字符存入字符
			res += s[i];
		}		
	}
	return res;
}

 

class Solution {
    public String decodeString(String s) {
        return dfs(s, 0)[0];
    }

    //首先解释下String[]是什么
    //当String[]的长度为2时,第二个元素为解码出的子字符串,
第一个元素为解码出的子字符串的最后字符']'在s中的下标
    //当String[]的长度为1时,数组中只存储了解码出的字符串
    //dfs函数的意思:对字符串s从i往后的子串进行解码,并存在数组里;
必要的时候还会在数组里存子串最后那个']'的下标
    private String[] dfs(String s, int i){
        StringBuilder res = new StringBuilder();
        //multi为k[encoded_string]的k,是一个正整数
        int multi = 0;
        while (i < s.length()){
            //当前字符为数字,需要更新multi的值
            //为啥要乘10?因为是从左往右扫描的,
如果k不是个位数而是n位整数的话就要通过不停的乘10来更新值
            if (s.charAt(i) >= '0' && s.charAt(i) <= '9')
                multi = 10 * multi + Integer.parseInt(String.valueOf(s.charAt(i)));
            //当前字符为'[',此时需要递归地去解码'['后面的子串
            else if (s.charAt(i) == '['){
                //子串从'['的下一位开始,用tmp保存解码的结果和子串最后的']'在s中的下标
                String[] tmp = dfs(s, i + 1);
                //更新i的值,由于在上一行的递归中子串以及子串内部的子串都被求出来了,
所以在外层就不用管它们了,直接把i跳到tmp[0]表示的位置
                i = Integer.parseInt(tmp[0]);
                //这个while循环达到了把k[encoded_string]内的
encoded_string在res后拼接k次的效果(这里的encoded_string就是tmp[1])
                while (multi > 0){
                    res.append(tmp[1]);
                    multi--;
                }
            }
            //当前字符为']',返回这个子串结尾处的下标和其解码结果
            else if (s.charAt(i) == ']'){
                return new String[] {String.valueOf(i), res.toString()};
            }
            //当前字符为非数字、非'['']',则把它拼接到res后
            else {
                res.append(String.valueOf(s.charAt(i)));
            }
            //i后移
            i++;
        }
        return new String[] {res.toString()};
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值