[Leedcode][JAVA][第394题][字符串解码][栈][类型转换]

239 篇文章 1 订阅
【问题描述】[中等]
给定一个经过编码的字符串,返回它解码后的字符串。

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

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

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

示例:

s = "3[a]2[bc]", 返回 "aaabcbc".
s = "3[a2[c]]", 返回 "accaccacc".
s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".



【解答思路】
1. 辅助栈法

在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(N)

 public String decodeString(String s) {
        StringBuilder res = new StringBuilder();
        int multi = 0 ; 
        LinkedList<Integer> stack_multi = new LinkedList<>();
        LinkedList<String> stack_res = new LinkedList<>();
        for(Character c: s.toCharArray()){
            if(c == '['){
                stack_multi.addLast(multi);
                stack_res.addLast(res.toString());
                multi = 0;
                res = new StringBuilder();
            }
            else if(c == ']'){
                StringBuilder tmp = new StringBuilder();
                int cur_multi =stack_multi.removeLast();
                for(int i = 0;i<cur_multi;i++){
                    tmp.append(res);
                }
                res = new StringBuilder(stack_res.removeLast()+tmp);
            }
            else if(c >='0' && c<='9'){
                //次数大于10时需要累计
                multi = multi *10 +Integer.parseInt(c+"");
            }
            else{
                res.append(c);
            }
        }
        return res.toString();

    }
2. 递归法

在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(N)

class Solution {
    //空间换时间,同时避免递归传这种不会改变的参数
    //String.charAt()会多一个越界的判断,其实这里不转为数组也可以,个人习惯
    char[] ss;

    public String decodeString(String s) {
        this.ss = s.toCharArray();
        return dfs(0)[0];
    }

    private String[] dfs(int i) {
        int nums = 0;
        StringBuilder res = new StringBuilder();
        while (i < ss.length) {
            //是数字,因为不一定只有个位,所以需要进位计算
            if (Character.isDigit(ss[i])) {
                nums = nums * 10 + (ss[i] - '0');
                //如果是'[',就是重复字符串的开始位置
            } else if (ss[i] == '[') {
                //因为可能会嵌套n[字符串],所以需要进入递归
                String[] temp = dfs(i + 1);  //这里是16行
                //将指针移动到结尾的']'位置,中间的内容在下面的while中已经填充完毕
                i = Integer.parseInt(temp[0]);
                //根据nums循环填充目标字符串
                while (nums > 0) {
                    res.append(temp[1]);
                    nums--;
                }
                //如果是']',说明已经输出完成,其实只在进入递归后有效,第一次调用dfs的栈帧永远不会走进这个判断
            } else if (ss[i] == ']') {
                //此处为什么是i呢?因为这层return到的是递归方法调用处,即返回至16行所在,不可能返回到初次调用的位置
                //所以需要记录']'出现的位置,至于为什么不+1,是因为走完16行所在的代码块会走到34行
                return new String[]{String.valueOf(i), res.toString()};
                //类似于2[abc]3[cd]ef中的ef,没有循环次数,可以直接填充
            } else {
                res.append(ss[i]);
            }
            //移动指针
            i++;  //这里是34行
        }
        return new String[]{res.toString()};
    }
}
class Solution {
    public String decodeString(String s) {
        return dfs(s, 0)[0];
    }
    private String[] dfs(String s, int i) {
        StringBuilder res = new StringBuilder();
        int multi = 0;
        while(i < s.length()) {
            if(s.charAt(i) >= '0' && s.charAt(i) <= '9') 
                multi = multi * 10 + Integer.parseInt(String.valueOf(s.charAt(i))); 
            else if(s.charAt(i) == '[') {
                String[] tmp = dfs(s, i + 1);
                i = Integer.parseInt(tmp[0]);
                while(multi > 0) {
                    res.append(tmp[1]);
                    multi--;
                }
            }
            else if(s.charAt(i) == ']') 
                return new String[] { String.valueOf(i), res.toString() };
            else 
                res.append(String.valueOf(s.charAt(i)));
            i++;
        }
        return new String[] { res.toString() };
    } 
}


【总结】
1.为什么用LinkedList不用Stack

基于 Vector 实现的栈 Stack底层是数组 扩容开销大
Java并不推荐使用java.util.stack来进行栈的操作,而是推荐使用一个双端队列deque
详情链接:https://www.cnblogs.com/cosmos-wong/p/11845934.html

2.细节

2.1 转字符串
1、toString,需要保证调用这个方法的类、方法、变量不为null,否则会报空指针。

2、String.valueOf。这个方法在使用的时候是有些特殊的。一般情况下,如果是确定类型的null传入,返回的是字符串“null”,而如果直接传入null,则会发生错误。
在这里插入图片描述

3、(String) 字符串类型强转。需要保证的是类型可以转成String类型。

2.2 、2.3 应用于提取字符串中的数字字符转整形

2.2 字符转整型

 Integer.parseInt(c + "");

2.3 字符串中某字符转整型

 Integer.parseInt(String.valueOf(s.charAt(i))); 
3.括号匹配 栈栈栈
4.包装类的用法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
转载链接:https://leetcode-cn.com/problems/decode-string/solution/decode-string-fu-zhu-zhan-fa-di-gui-fa-by-jyd/
参考链接:https://blog.csdn.net/yangzhaomuma/article/details/51173138

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值