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

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

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

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

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

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

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

示例 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"

提示:

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"

算法图解(以 "3[a2[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: 题目保证输入有效,但实际应用需要添加校验:

  • 括号匹配检查
  • 数字后面必须跟 [
  • 方括号内不能为空
相关推荐
杨云龙UP2 小时前
Docker MySQL 5.7 全库备份到异地服务器实践记录_20260427
linux·运维·服务器·数据库·mysql·docker·容器
lcj25112 小时前
精选5大高频链表与数组算法详解:从旋转数组到链表公共节点,LeetCode实战代码+图解全解析
算法·leetcode·链表
xin_nai2 小时前
LeetCode热题100(Java)(4)子串
java·算法·leetcode
Coffeeee2 小时前
用了一段时间的AI了,忍不住想吐点槽,你的AI帮你提效了吗?
前端·人工智能·程序员
剩下了什么2 小时前
dockerfile-知识概念介绍
linux·运维·服务器
一只数据集2 小时前
机器学习多领域综合数据集分析-包含基因表达时间序列分类回归数据-适用于算法训练模型评估科研应用
人工智能·算法·数据分析
勤劳的进取家2 小时前
如何配置服务器代理转发
运维·服务器
jialan752 小时前
上海服务器 CentOS7.6 mysql8 redis jdk17 Tomcat10
运维·服务器·redis
sulikey2 小时前
个人Linux操作系统学习笔记1 - Linux权限与工具
linux·笔记·学习