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: 题目保证输入有效,但实际应用需要添加校验:

  • 括号匹配检查
  • 数字后面必须跟 [
  • 方括号内不能为空
相关推荐
Cosolar44 分钟前
LlamaIndex索引类型全解析:原理与实战指南
运维·服务器
小雨下雨的雨2 小时前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
方便面不加香菜3 小时前
Linux--基础IO(一)
linux·运维·服务器
xieliyu.5 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
一条小锦吕*5 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
鼎讯信通5 小时前
风电光缆运维提质增效:G-4000A 光缆故障追踪仪破解风场巡检难题
运维·网络·数据库
ZC跨境爬虫6 小时前
跟着 MDN 学JavaScript day_7:数学运算与逻辑判断实战测试
开发语言·前端·javascript·学习·ecmascript
三十..6 小时前
MySQL 从入门到高可用架构实战精要
运维·数据库·mysql
fangdengfu1236 小时前
ES分析系统各个服务日志占用量
java·前端·elasticsearch
跨境数据猎手7 小时前
大数据在电商行业的应用
大数据·运维·爬虫