CodeTop Top 300 热门题目8-字符串解码

394-字符串解码 https://leetcode.cn/problems/decode-string/

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

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

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

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

测试用例保证输出的长度不会超过 105。

示例 1:

输入:s = "3a2bc"

输出:"aaabcbc"

示例 2:

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

输出:"accaccacc"

示例 3:

输入:s = "2abc3cdef"

输出:"abcabccdcdcdef"

示例 4:

输入:s = "abc3cdxyz"

输出:"abccdcdcdxyz"

提示:

1 <= s.length <= 30

s 由小写英文字母、数字和方括号 '\[\]' 组成

s 保证是一个 有效 的输入。

s 中所有整数的取值范围为 1, 300

"字符串解码"是经典的栈应用题,我给你详细解答。

python 复制代码
def decodeString(s: str) -> str:
    """
    解码字符串
    
    示例:
    "3[a]2[bc]" → "aaabcbc"
    "3[a2[c]]" → "accaccacc"
    "2[abc]3[cd]ef" → "abcabccdcdcdef"
    
    算法思路:使用栈处理嵌套结构
    - 遇到数字:记录重复次数
    - 遇到 '[':将当前状态压栈,开始新的解码
    - 遇到字母:追加到当前结果
    - 遇到 ']':弹栈,合并结果
    
    时间复杂度:O(n),每个字符处理一次
    空间复杂度:O(n),栈的深度
    """
    
    # 栈:存储 [重复次数, 之前的结果字符串]
    stack = []
    
    # 当前正在构建的结果字符串
    current_str = ""
    
    # 当前的重复次数
    current_num = 0
    
    i = 0
    while i < len(s):
        char = s[i]
        
        # 情况1: 遇到数字,解析完整数字(可能有多位)
        if char.isdigit():
            # 将数字字符转换为数字
            # 注意:可能是多位数,如 "12[ab]" 中的 12
            current_num = current_num * 10 + int(char)
            i += 1
            
        # 情况2: 遇到 '[',将当前状态压栈,开始新的解码
        elif char == '[':
            # 将 [重复次数, 当前结果] 压入栈
            # 例如 "3[a2[c]]" 遇到第一个 '[' 时:
            # 压入 [3, ""],然后重置 current_num 和 current_str
            stack.append((current_num, current_str))
            
            # 重置状态,准备解码 [] 内的内容
            current_num = 0
            current_str = ""
            i += 1
            
        # 情况3: 遇到字母,追加到当前结果
        elif char.isalpha():
            current_str += char
            i += 1
            
        # 情况4: 遇到 ']',弹栈并合并结果
        elif char == ']':
            # 弹栈,获取之前的重复次数和字符串
            prev_num, prev_str = stack.pop()
            
            # 当前字符串重复 prev_num 次
            # 例如 current_str="cc", prev_num=2 → "cccc"
            current_str = prev_str + current_str * prev_num
            
            i += 1
    
    return current_str


# 测试用例
if __name__ == "__main__":
    # 测试1: 基本情况
    test1 = "3[a]2[bc]"
    print(f"输入: {test1}")
    print(f"输出: {decodeString(test1)}")  # "aaabcbc"
    print(f"预期: aaabcbc")
    print()
    
    # 测试2: 嵌套情况
    test2 = "3[a2[c]]"
    print(f"输入: {test2}")
    print(f"输出: {decodeString(test2)}")  # "accaccacc"
    print(f"预期: accaccacc")
    print()
    
    # 测试3: 混合情况
    test3 = "2[abc]3[cd]ef"
    print(f"输入: {test3}")
    print(f"输出: {decodeString(test3)}")  # "abcabccdcdcdef"
    print(f"预期: abcabccdcdcdef")
    print()
    
    # 测试4: 多位数字
    test4 = "10[a]"
    print(f"输入: {test4}")
    print(f"输出: {decodeString(test4)}")  # "aaaaaaaaaa"
    print(f"预期: aaaaaaaaaa")
    print()
    
    # 测试5: 无编码
    test5 = "abc"
    print(f"输入: {test5}")
    print(f"输出: {decodeString(test5)}")  # "abc"

算法图解(以 "3a2\[c]" 为例)

复制代码
字符串:  3  [  a  2  [  c  ]  ]
索引:    0  1  2  3  4  5  6  7

初始状态:
  stack = []
  current_str = ""
  current_num = 0

步骤1: i=0, char='3' (数字)
  current_num = 0 * 10 + 3 = 3
  
步骤2: i=1, char='[' (左括号)
  stack = [(3, "")]
  current_str = ""
  current_num = 0
  
步骤3: i=2, char='a' (字母)
  current_str = "a"
  
步骤4: i=3, char='2' (数字)
  current_num = 0 * 10 + 2 = 2
  
步骤5: i=4, char='[' (左括号)
  stack = [(3, ""), (2, "a")]
  current_str = ""
  current_num = 0
  
步骤6: i=5, char='c' (字母)
  current_str = "c"
  
步骤7: i=6, char=']' (右括号)
  弹栈: prev_num=2, prev_str="a"
  current_str = "a" + "c" * 2 = "acc"
  stack = [(3, "")]
  
步骤8: i=7, char=']' (右括号)
  弹栈: prev_num=3, prev_str=""
  current_str = "" + "acc" * 3 = "accaccacc"
  stack = []

最终结果: "accaccacc"

关键点解释

1. 为什么要用栈?

  • 嵌套结构天然适合用栈(类似括号匹配)
  • 遇到 '[' 表示进入新的层级,需要保存当前状态
  • 遇到 ']' 表示当前层级结束,需要回到上一层

2. 数字解析为什么是 current_num * 10 + int(char)

处理多位数字:

复制代码
"12[ab]"
i=0: char='1' → current_num = 0*10 + 1 = 1
i=1: char='2' → current_num = 1*10 + 2 = 12

3. 弹栈时的合并公式

python 复制代码
current_str = prev_str + current_str * prev_num

"3[a2[c]]" 为例:

  • 弹出 [2, "a"] 后:
    • current_str = "c""a" + "c" * 2 = "acc"
  • 弹出 [3, ""] 后:
    • current_str = "acc""" + "acc" * 3 = "accaccacc"

复杂度分析

复杂度 分析
时间 O(n),每个字符最多处理一次
空间 O(n),栈的深度最坏为 O(n)(全嵌套)

扩展思考

Q: 如果字符串格式不正确怎么办?

A: 题目保证输入有效,但实际应用需要添加校验:

  • 括号匹配检查
  • 数字后面必须跟 [
  • 方括号内不能为空
相关推荐
咸鱼老弟1 分钟前
AI Agent 的"自主性悖论"——为什么给它的自由度越大,越要配一套更硬的护栏
前端·人工智能
susplus4 分钟前
【ARM 裸机开发 (IMX6ULL-mini)】GNU工具、Makefile 工程构建、链接脚本详解|C 语言点灯 + 蜂鸣器驱动
linux·arm·makefile·imx6ull
Shadow(⊙o⊙)5 分钟前
Linux进阶知识1.0
linux·运维·服务器
>Andre<40 分钟前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件
默_笙43 分钟前
💫 闭包是个背包:拆解小米前端面试题里的三道"闭包陷阱"
前端·javascript·面试
用户0510122572961 小时前
Linux下有关QT显示环境变量设置
linux·嵌入式
闲云自留地1 小时前
告别命令恐惧症,openEuler 基础操作 + 文本 + 网络管理实战
linux·运维·云计算
天若有情6731 小时前
粒子星空背景单页HTML模板|炫酷动态星空特效网页(纯前端)
前端·html·css动画·网页特效·粒子星空·静态网页模版
工业涂料百问1 小时前
【趋势前沿】系列(三)工业涂料国产替代的三个台阶:航空、海工、电子的突破路径与认证壁垒
前端
wabs6661 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树