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,建议多练习,熟能生巧。
相关推荐
Yang_jie_038 小时前
笔记:数据结构(栈是否使用底指针以及头指针的初始化值)
数据结构·笔记·算法
海石10 小时前
【JS击败90%】前缀和+定长滑动窗口
算法·leetcode
Tisfy10 小时前
LeetCode 2685.统计完全连通分量的数量:DFS求每个连通块的边点数
算法·leetcode·深度优先··题解·连通图·全连通分量
海石10 小时前
1次遍历,空间复杂度击败100%,时间复杂度击败85%
算法·leetcode
lueluelue4711 小时前
LeetCode:滑动窗口
数据结构·算法·leetcode
码少女11 小时前
数据结构——冒泡排序及优化
数据结构·算法·排序算法
青梅橘子皮12 小时前
string---入门OJ题(1)
数据结构·算法
小高Baby@12 小时前
单链表的删操作
数据结构·算法·golang
qq_4542450312 小时前
BasicMethod.Map 设计框架:8 个并行基础模块的数学根基与实现
数据结构·算法·c#
青山木12 小时前
Hot 100 --- 二叉树与递归
java·数据结构·算法·leetcode·深度优先