Leetcode刷题日记-No394字符串解码

        题目链接:https://leetcode.cn/problems/decode-string/

        思路:该题目实际是一个括号匹配的问题,括号匹配问题用的数据结构就是栈。核心逻辑是构造两个栈(数字栈+字母栈),从左到右遍历字符串,遇到数字压入数字栈,遇到括号数字栈弹出,并将括号压入字母栈,遇到另一个匹配的括号时弹出所有字母和括号,并结合数字决定重复次数输出。

        但是实际在写代码时候也遇到很多问题,有些细节条件还是没有考虑的太周到,最后还是在本异一点一点debug出来了,花了多半天的时间。代码如下:

class Solution {
    public static String decodeString(String s) {
        Stack<String> numStack = new Stack<String>();
        //用于将类似1,0的字符串拼接为10
        Stack<String> tranNumStack = new Stack<String>();
        Stack<String> opStack = new Stack<String>();
        StringBuilder result = new StringBuilder();
        int index = 0;
        while (index < s.length()) {
            if (Character.isLetter(s.charAt(index)) || "[".equals(s.substring(index, index+1))) {
                if(!tranNumStack.isEmpty()) {
                    //先弹出之前的数字栈中的字符并转换为数字重新压入
                    StringBuilder builder = new StringBuilder();
                    while (!tranNumStack.isEmpty()) {
                        builder.append(tranNumStack.pop());
                    }
                    //倒序并存入numStack栈
                    numStack.push(builder.reverse().toString());
                }
                //字母和左括号压入字符栈
                while (index < s.length() && (Character.isLetter(s.charAt(index)) || "[".equals(s.substring(index, index+1)))) {
                    opStack.push(s.substring(index, index+1));
                    index++;
                }
            }else if(Character.isDigit(s.charAt(index))) {
                //数字直接压栈
                while (index < s.length() && Character.isDigit(s.charAt(index))) {
                    tranNumStack.push((s.substring(index, index+1)));
                    index++;
                }
            }else if("]".equals(s.substring(index, index+1))) {
                StringBuilder sb = new StringBuilder();
                //右括号开始出栈
                while(!"[".equals(opStack.peek())) {
                    sb.insert(0, opStack.pop());
                }
                //弹出左括号
                opStack.pop();
                //与数字结合生成解码后的字符串并压栈
                if(!numStack.isEmpty()) {
                    String join = String.join("", Collections.nCopies(Integer.parseInt(numStack.pop()), sb.toString()));
                    opStack.push(join);
                }
                index++;
            }
        }
        //将所有的字符逆序输出
        while (!opStack.isEmpty()) {
            result.insert(0, opStack.pop());
        }
        return result.toString();
    }
}

比较关键的逻辑总结起来有以下几点:

        1.除了数字栈numStack和字符栈opStack之外,加入了另一个临时数字栈tranNumStack,目的是将多位数(如:10)合并为一个真实的数字再压入numStack中。

         2.遇到数字直接入栈

        3.遇到字符(非右括号),先把前面暂存的倍数(存在tranNumStack)转换为真实的数字,并存入numStack中(注意倒序)。接着依次将字符存入opStack之中。

        4.遇到右括号,就需要处理之前与之匹配的左括号及倍数,转换为需要的形式,并存入opStack

        5.将opStack中的所有元素倒序依次输出。

        总体感受,这种中等难度的题目想要一时半会解出来还是比较难的(至少对于我来讲),可以结合一些题解来思考,但是最关键的还是要自己静下来一步一步思考,甚至在本地一步一步debug。如果自己没有很深的思考,别人的代码也很难看懂,就算看懂了后面还是会容易忘记。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值