071字符串解码

字符串解码

题目链接:https://leetcode.cn/problems/decode-string/description/?envType=study-plan-v2\&envId=top-100-liked

我的解答:

复制代码

分析:有一点点思路想用双栈,但是最后没能实现出来。

看了官方题解后的解答:

复制代码
//方法一:栈操作
//时间复杂度:渐进时间复杂度为 O(S+∣s∣),即 O(S),S为解码后得出的字符串长度。
//空间复杂度:O(S),S为解码后得出的字符串长度。
int ptr;
public String decodeString(String s) {
    LinkedList<String> stack = new LinkedList<>();
    int n = s.length();
    ptr = 0;
    while(ptr < n){
        char cur = s.charAt(ptr);
        //当前字符为数字
        if(Character.isDigit(cur)){
            String digit = getDigit(s);
            stack.addLast(digit);
        }
        //当前字符为字母或'['
        else if(Character.isLetter(cur) || cur == '['){
            stack.addLast(String.valueOf(cur));
            ptr++;
        }
        //当前字符为']'
        else{
            ptr++;
            LinkedList<String> sub = new LinkedList<>();
            //收集子串
            while(!"[".equals(stack.peekLast())){
                sub.addLast(stack.removeLast());
            }
            Collections.reverse(sub);
            //左括号出栈
            stack.removeLast();
            String output = getString(sub);
            int repTime = Integer.parseInt(stack.removeLast());
            StringBuffer t = new StringBuffer();
            //构造字符串
            while(repTime-- > 0){
                t.append(output);
            }
            //将构造好的字符串入栈
            stack.addLast(t.toString());
        }
    }
    return getString(stack);
}

public String getDigit(String s){
    StringBuffer sb = new StringBuffer();
    while(Character.isDigit(s.charAt(ptr))){
        sb.append(s.charAt(ptr++));
    }
    return sb.toString();
}

public String getString(LinkedList<String> temp){
    StringBuffer sb = new StringBuffer();
    for(String str : temp){
        sb.append(str);
    }
    return sb.toString();
}

//方法二:递归
//时间复杂度:渐进时间复杂度为 O(S+∣s∣),即 O(S),S为解码后得出的字符串长度。
//空间复杂度:O(S),S为解码后得出的字符串长度。
int ptr = 0;
public String decodeString(String s) {
    if(ptr == s.length() || s.charAt(ptr) == ']'){
        return "";
    }
    String res = "";
    char cur = s.charAt(ptr);
    //遇到数字,开始解析数字
    if(Character.isDigit(cur)){
        int repTime = getDigit(s);
        //过滤左括号
        ptr++;
        //解析括号内的字符串
        String sub = decodeString(s);
        //过滤右括号
        ptr++;
        //构造字符串
        while(repTime-- > 0){
            res += sub;
        }
    }
    else{
        res += String.valueOf(s.charAt(ptr++));
    }
    return res + decodeString(s);
}

public int getDigit(String s){
    int repTime = 0;
    while(Character.isDigit(s.charAt(ptr))){
        repTime = repTime * 10 + (s.charAt(ptr++) - '0');
    }
    return repTime;
}

分析:

​ 1、方法一的解题思路:用LinkedList模拟栈,方便从栈底往栈顶遍历。遍历字符串s,若遇到数字则获取数字并入栈;若遇到字母或左括号,直接入栈;若遇到右括号,开始收集和处理当前括号中的字符串,重复此操作直到遍历完字符串s,最后栈中从栈底到栈顶的字符串拼接起来就是解码后的字符串。此方法第一需要明确,我们需要从栈底往栈顶遍历元素,所以就不能直接使用封装好的栈结构,只能自己模拟栈;第二,此方法涉及到许多API的调用,我还不太熟悉这些API;第三,当出现数字时,可能有连续多个数字字符组成一个数字。

​ 2、方法二的解题思路:采用递归方法构造子串。如果当前位置为数字位,那么后面一定包含一个用方括号表示的字符串,即属于这种情况:k... ,我们先解析出这个数字,然后递归构造括号中的子串,最后根据数字构造出解析后的子串,我们把 k... 解析结束后,再次调用递归函数,解析右括号右边的内容。

总结

  • 本题主要有两种解题方法,分别为栈操作、递归。思路不难想到,但实现起来较为复杂,细节较多,涉及许多字符和字符串相关的API,建议多练习,熟能生巧。
相关推荐
Darling噜啦啦4 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠5 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾5 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres8215 天前
算法复键——树状数组
数据结构·算法
想吃火锅10055 天前
【leetcode】121.买卖股票的最佳时机js/c++
算法·leetcode·职场和发展
牛油果子哥q5 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒5 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
退休倒计时5 天前
【每日一题】LeetCode 146. LRU 缓存 TypeScript
算法·leetcode·缓存·typescript
WL学习笔记5 天前
单项不带头不循环链表
数据结构·链表
小糯米6015 天前
JS 数组
数据结构·算法·排序算法