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

LeetCode-394. 字符串解码

原题链接

问题描述

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

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

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

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

测试用例保证输出的长度不会超过 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为结果字符串总长度

相关推荐
.小墨迹1 小时前
局部规划中的TEB,DWA,EGOplanner等算法在自动驾驶中应用?
开发语言·c++·人工智能·学习·算法·机器学习·自动驾驶
AI科技星2 小时前
张祥前统一场论 22 个核心公式及常数
服务器·人工智能·线性代数·算法·矩阵·概率论
苏婳6662 小时前
阿里巴巴校招软件笔试题经典
算法
阿猿收手吧!2 小时前
【数据结构】高效掌握并查集:核心原理与实战
数据结构·算法
励ℳ2 小时前
机器学习之线性回归算法:从原理到实践的全面解析
算法·机器学习·线性回归
_Twink1e2 小时前
[算法教学]一、前置知识
算法
技小宝2 小时前
如何在WPS/Excel中批量翻译长文本?
经验分享·职场和发展·excel·wps
MicroTech20252 小时前
微算法科技(NASDAQ: MLGO)使用量子傅里叶变换(QFT),增强图像压缩和滤波效率
科技·算法·量子计算
㓗冽2 小时前
矩阵问题(二维数组)-基础题70th + 发牌(二维数组)-基础题71th + 数字金字塔(二维数组)-基础题72th
c++·算法·矩阵