【栈】——字符串解码

168 阅读2分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

题目

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

来源:力扣(LeetCode)

思路

1.看到这道题第一感觉应该和括号匹配问题有些类似,遇到的字符有这几种类型

  • [
  • ]
  • 0~9
  • a~z

2.实际上最早的字符串应该是从内部最想匹配生成的,比如3[a2[c]]里面的2c要比外面的3[a2[c]]先组成字符串,每次遇到]的情况就是说明一次新的字符串构建的过程

3.用一个栈numStack存储遇到的数字,一个栈strStack存储拼接成的字符串

4.分类讨论各种情况

  • [

    说明开始进入一个新的匹配阶段,需要保留上一次字符串拼接的结果以及上一次字符串前面的数

    然后需要把num和res都变成初始值

numStack.addLast(num); 
strStack.addLast(res.toString()); 
res = new StringBuilder(); 
num = 0;
  • ]

    说明可以开始匹配了,从保存次数的numStack栈顶取出个数,然后进行字符串的拼接

  • 0~9 只需要更新num的值即可,需要注意进位

num = num * 10 + Integer.parseInt(c + "");
  • a~z

直接添加到res中

代码

class Solution {
    public String decodeString(String s) {
        StringBuilder res = new StringBuilder();
        char[] chars = s.toCharArray();
        LinkedList<Integer> numStack = new LinkedList<>();
        LinkedList<String> strStack = new LinkedList<>();
        int num = 0;
        for (char c : chars) {
            if (c == '[') {
                numStack.addLast(num);
                strStack.addLast(res.toString());
                res = new StringBuilder();
                num = 0;
            } else if (c == ']') {
                StringBuilder temp1 = new StringBuilder();
                int times = numStack.removeLast();
                for (int i = 0; i < times; i++) {
                    temp1.append(res);
                }
                res = new StringBuilder(strStack.removeLast() + temp1);

            } else if (c >= '0' && c <= '9') {
                num = num * 10 + Integer.parseInt(c + "");
            } else { //普通符号
                res.append(c);
            }
        }
        return res.toString();
    }
}