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: 题目保证输入有效,但实际应用需要添加校验:
- 括号匹配检查
- 数字后面必须跟
[ - 方括号内不能为空
