当前位置: 首页 > news >正文

【LeetCode 热题 100】394. 字符串解码

Problem: 394. 字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N + M)
    • 空间复杂度:O(N) 或 O(M)

整体思路

这段代码旨在解决一个涉及嵌套结构的 字符串解码 (Decode String) 问题。编码规则是 k[encoded_string],表示 encoded_string 这部分内容重复 k 次。由于括号可以嵌套,例如 3[a2[c]],这个问题具有天然的递归或栈式结构。

该算法巧妙地采用了 双栈(Two Stacks) 的迭代方法来处理这种嵌套关系,避免了显式递归。

  1. 数据结构选择

    • strStack (字符串栈): 用于保存遇到 [ 之前的字符串部分。当解码一个内部括号时,栈顶的字符串就是其解码结果需要拼接的前缀。
    • numStack (数字栈): 用于保存与 [ 对应的重复次数 k
    • StringBuilder curr: 用于高效地构建当前正在处理的、位于同一嵌套层级的字符串。
    • int k: 一个临时变量,用于解析可能由多位数字组成的重复次数。
  2. 核心遍历与状态管理逻辑

    • 算法通过单次遍历输入字符串 s 的每个字符来驱动。根据字符的类型,执行不同的状态转换:
      • 遇到数字 ('0'-'9'): 将其累加到 k 变量中。k = k * 10 + c - '0' 这个技巧可以正确地解析多位数(如 “10”, “123”)。
      • 遇到左括号 ('['): 这标志着进入了一个新的、更深的嵌套层级。此时,必须“保存”当前层级的状态,以便稍后恢复。
        • 将当前的重复次数 k 压入 numStack
        • 将当前已经构建好的字符串 curr 压入 strStack
        • 重置 kcurr,为新的嵌套层级做准备。
      • 遇到右括号 (']'): 这标志着一个嵌套层级的结束。此时,需要“恢复”上一层级的状态并执行解码。
        • numStack 弹出重复次数 repeat
        • strStack 弹出上一层级的字符串前缀 prev
        • 将当前 curr 所代表的字符串重复 repeat 次。
        • 将重复后的字符串与前缀 prev 合并,形成新的 curr。这就完成了从内层到外层的解码与合并。
      • 遇到字母 (else): 这是一个普通字符,直接追加到当前层级的字符串构建器 curr 的末尾。
  3. 返回结果

    • 当遍历完整个输入字符串后,curr 中就包含了完全解码后的最终字符串,将其返回即可。

这个双栈方法优雅地模拟了递归调用过程:[ 相当于递归深入,] 相当于递归返回。

完整代码

class Solution {/*** 解码一个按特定规则编码的字符串。* @param s 编码后的字符串,例如 "3[a2[c]]"* @return 解码后的字符串,例如 "accaccacc"*/public String decodeString(String s) {// strStack: 用于保存遇到'['之前的字符串部分,作为解码时的前缀。Deque<String> strStack = new ArrayDeque<>();// numStack: 用于保存'['前的重复次数 k。Deque<Integer> numStack = new ArrayDeque<>();// k: 临时变量,用于解析可能的多位数字。int k = 0;// curr: 一个 StringBuilder,用于高效地构建当前嵌套层级的字符串。StringBuilder curr = new StringBuilder();// 遍历输入字符串的每一个字符for (char c : s.toCharArray()) {if (c >= '0' && c <= '9') {// 如果是数字,更新 k 的值。k * 10 的技巧可以处理多位数。k = k * 10 + c - '0';} else if (c == '[') {// 如果是左括号,表示进入新的嵌套层级。// 1. 将当前的重复次数 k 压入数字栈numStack.push(k);// 2. 将当前已构建的字符串 curr 压入字符串栈strStack.push(curr.toString());// 3. 重置 k 和 curr,为新层级做准备k = 0;curr = new StringBuilder();} else if (c == ']') {// 如果是右括号,表示一个嵌套层级结束,需要解码。// 1. 弹出该层级对应的重复次数int repeat = numStack.pop();// 2. 弹出上一层的字符串前缀String prev = strStack.pop();// 3. 将当前层级的字符串(curr)重复指定次数String repeated = curr.toString().repeat(repeat);// 4. 将重复后的字符串与前缀合并,更新为新的当前层字符串curr = new StringBuilder(prev + repeated);} else {// 如果是普通字母,直接追加到当前层级的字符串中curr.append(c);}}// 循环结束后,curr 中即为最终完全解码的字符串return curr.toString();}
}

时空复杂度

时间复杂度:O(N + M)

  1. N 的部分:算法的主体是一个 for 循环,它遍历输入字符串 s 一次。设 s 的长度为 N。这个扫描过程本身是 O(N) 的。
  2. M 的部分
    • 在循环内部,最耗时的操作是 curr.toString().repeat(repeat) 和随后的字符串拼接。
    • 这些操作的总成本不取决于 N,而是取决于最终解码后字符串的长度,我们称之为 M
    • 每一个最终生成在结果字符串中的字符,都是通过 appendrepeat 操作产生的。所有这些生成操作的总和与最终字符串的长度 M 成正比。
  3. 综合分析
    • 总时间复杂度是扫描输入字符串的时间加上生成输出字符串的时间。
    • 因此,最终的时间复杂度为 O(N + M),其中 N 是输入字符串的长度,M 是输出字符串的长度。

空间复杂度:O(N) 或 O(M)

  1. 主要存储开销:空间主要由两个栈 strStacknumStack 以及 StringBuilder curr 占用。
  2. 空间大小
    • numStack 的大小与嵌套深度成正比,最多为 O(N)。
    • strStack 存储的是中间的字符串片段。在最坏的情况下,例如 2[a2[b2[c...]]],栈中存储的字符串总长度可能与最终输出字符串的长度 M 相关。
    • 然而,在更典型的情况下,例如 a[b[c...]],栈中存储的字符串总长度(“a”, “ab”, “abc” …)可以被输入长度 N 所限制。
    • 考虑到各种情况,一个比较合理的上界是 O(N + M),但通常在分析中会简化为 O(N)O(M),这取决于哪一个在特定用例中是主导因素。在大多数面试场景下,将其分析为 O(N) 是被接受的,因为它与输入的规模和结构直接相关。

综合分析
算法的辅助空间复杂度主要由栈的内容决定,其大小与输入的嵌套深度和字符串片段长度有关。一个合理的估计是 O(N)

http://www.dtcms.com/a/310273.html

相关文章:

  • 合并对象 递归注意对象的合并时机
  • 20257月29日-8月2日训练日志
  • Codeforces Round 1040 (Div. 2)(补题)
  • Java函数式编程之【基本数据类型流】
  • Thymeleaf 模板引擎原理
  • 删除MicroGame
  • 设计模式之职责链模式
  • Android 中 Intent 的显式和隐式使用方式
  • Alpine Linux 设置镜像的时区
  • ONLYOFFICE 深度解锁系列.14-如何在ONLYOFFICE表格中调用异步API,集成外部数据源
  • R语言基础图像及部分调用函数
  • MyEclipse启动OutOfMemoryError内存溢出
  • 笔试——Day25
  • 【数据结构入门】顺序表
  • linux81 shell通配符:[list],‘‘ ``““
  • AI数字人:会“呼吸”的虚拟人如何改变我们的世界?
  • 倒计时!2025国自然放榜时间锁定
  • DreamBoards 借助 DreamHAT+ 雷达插件为 Raspberry Pi 提供 60GHz 毫米波雷达
  • 使用Excel解析从OData API获取到的JSON数据
  • AR智能巡检系统:制造业设备管理的效率革新
  • 【难点】敬语
  • 2025年文生图模型stable diffusion v3.5 large的全维度深度解析
  • Altium 移除在原理图之外的元器件
  • Vue3 Vue3中的响应式原理
  • 从零开始:Python编程快速入门指南
  • 超算中尝试安装dify(失败)
  • Docker 实战 -- Nextcloud
  • 茶叶蛋大冒险小游戏流量主微信抖音小程序开源
  • Nginx 配置导致 “无法建立到 ws://xxx/_stcore/stream 的连接” 的解决方案
  • 使用ai的共识,技巧,避坑。