LeetCode-394. 字符串解码 递归思路

LeetCode-394. 字符串解码

原题链接

问题描述

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

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

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

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

测试用例保证输出的长度不会超过 10^5

测试用例

示例 1:

输入:s = "3[a]2[bc]"

输出:"aaabcbc"

示例 2:

输入:s = "3[a2[c]]"

输出:"accaccacc"

示例 3:

输入:s = "2[abc]3[cd]ef"

输出:"abcabccdcdcdef"

示例 4:

输入:s = "abc3[cd]xyz"

输出:"abccdcdcdxyz"

解题思路

一开始看到题目的测试用例其实第一反应就是递归 因为考虑到是先要读取到括号中的内容然后再回溯通过前面的数字进行累加 并且测试用例2中出现了层级嵌套 因此天然就是递归的结构 ,那思路就很明了了 使用StringBuilder对下一层递归的返回值进行累加即可。

不过我一开始做的时候有点碰壁 因为我将index作为参数进行传递 导致dfs 中递归调用处理括号内部逻辑时,外层的index并没有随着内层的执行而向后移动。导致内层处理完了,外层又从老位置开始,或者根本不知道跳到哪里。

代码如下

java 复制代码
class Solution {
    /**
     * 最初的版本
     * 错误记录点:
     * 1. 指针传递问题:index 是按值传递的,dfs 递归回来后父层的 index 没有更新,导致死循环或解析错误。
     * 2. 逻辑覆盖不全:只处理了"前导字母 + 一组数字括号",无法处理"abc3[a]2[b]"这种并列多组的情况。处理完3[a]就停止了
     * 3. 递归出口不全。
     */
    public String decodeString(String s) {
        return dfs(s, 0);
    }

    public String dfs(String s, int index) {
        StringBuilder sbu = new StringBuilder();

        // 1. 先读取前面的字母
        while (index < s.length() && isChar(s.charAt(index))) {
            sbu.append(s.charAt(index++));
        }

        // 2. 判断是否结束
        if (index == s.length() || s.charAt(index) == ']') {
            return sbu.toString();
        }

        // 3. 处理数字和括号
        if (isNumber(s.charAt(index))) {
            StringBuilder n = new StringBuilder();
            // 读取数字
            while (s.charAt(index) != '[') {
                n.append(s.charAt(index++));
            }
            
            // 递归调用(问题:这里的 index+1 结果没有反馈给当前层的 index)
            String plus = dfs(s, index + 1);
            
            int times = Integer.parseInt(n.toString());
            while (times > 0) {
                sbu.append(plus);
                times--;
            }
        }

        // 错误点:执行完上面逻辑就直接返回了,如果字符串后面还有内容(如 "3[a]bc" 中的 bc)会被丢弃
        return sbu.toString();
    }

    public boolean isNumber(char ch) {
        return ch >= '0' && ch <= '9';
    }

    public boolean isChar(char ch) {
        return ch >= 'a' && ch <= 'z';
    }
}

正解

使用一个全局的index 这样外层就可以知道遍历到哪了 使用while(index<s.length())作为出口条件即可
代码如下

java 复制代码
class Solution {
    // 使用全局变量 index,确保在递归调用过程中,所有层级共享同一个遍历进度
    int index = 0;

    public String decodeString(String s) {
        // ans 用于存储当前递归层级解析出来的字符串
        StringBuilder ans = new StringBuilder();
        // n 用于存储数字字符串(即括号前需要重复的次数)
        StringBuilder n = new StringBuilder();

        while (index < s.length()) {
            char ch = s.charAt(index);

            if (isChar(ch)) {
                // 情况1:如果是普通字母,直接追加到当前层级的结果中
                ans.append(ch);
                index++;
            } 
            else if (isNumber(ch)) {
                // 情况2:如果是数字,累加到 n 中(处理多位数的情况,如 100[a])
                n.append(ch);
                index++;
            } 
            else if (ch == '[') {
                // 情况3:遇到左括号 '['
                index++; // 跳过 '[',进入下一层递归
                
                // 【核心】递归调用:去处理括号里面的内容,返回括号内解码后的字符串
                String plus = decodeString(s);
                
                // 将之前记录的数字字符串转为整数
                int times = Integer.parseInt(n.toString());
                
                // 根据倍数 times,将返回的子字符串重复追加到当前结果 ans 中
                while (times > 0) {
                    ans.append(plus);
                    times--;
                }
                
                // 重复结束后,清空数字记录器 n,以便处理同级的下一个重复块
                n.setLength(0);
            } 
            else {
                // 情况4:遇到右括号 ']'
                index++; // 跳过 ']'
                // 当前括号层级处理完毕,返回当前层级构造好的字符串
                return ans.toString();
            }
        }
        
        // 整个字符串遍历结束,返回最终结果
        return ans.toString();
    }

    /**
     * 判断字符是否为数字
     */
    public boolean isNumber(char ch) {
        return ch >= '0' && ch <= '9';
    }

    /**
     * 判断字符是否为小写字母
     */
    public boolean isChar(char ch) {
        return ch >= 'a' && ch <= 'z';
    }
}

时间复杂度:O(L)

L为结果字符串总长度

相关推荐
888CC++1 小时前
如何在 C 语言中进行程序调试?
前端·javascript·算法
(●—●)橘子……3 小时前
力扣第503场周赛练习理解
python·学习·算法·leetcode·职场和发展·周赛
明志数科4 小时前
4D时序标注技术详解:让机器人理解连续动作的数据基础
java·算法·机器人
KaMeidebaby5 小时前
卡梅德生物技术快报|原核表达系统工艺优化:包涵体重折叠 + 分子筛纯化实现功能 RBD 高效制备,附全参数配置
前端·人工智能·算法·数据挖掘·数据分析
无限码力5 小时前
携程0510笔试真题【单数组交换】
算法·携程笔试·携程笔试真题·携程0510笔试真题
BlockWay6 小时前
WEEX Labs 周度观察:微软-OpenAI 合作调整与AI 多云趋势
大数据·人工智能·算法·安全·microsoft
风筝在晴天搁浅6 小时前
快手 CodeTop LeetCode 224.基本计算器
数据结构·算法·leetcode
Smoothcloud润云6 小时前
5大功能精修,重构AI算力使用体验!
java·人工智能·windows·算法·重构·编辑器·sublime text
计算机安禾6 小时前
【算法分析与设计】第41篇:确定性与非确定性多项式时间:P与NP的形式化
算法