news 2026/10/28 6:30:49

LeetCode 91题解码方法:动态规划解法与边界处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 91题解码方法:动态规划解法与边界处理

1. 问题概述与核心难点

LeetCode 91题"Decode Ways"是一个经典的动态规划问题,要求计算给定数字字符串的解码方式总数。题目描述为:一条包含字母A-Z的消息通过'A'->1,'B'->2...'Z'->26的方式进行了编码。给定一个只包含数字的非空字符串,请计算解码方法的总数。

这个问题的核心难点在于处理数字字符串中的边界条件:

  • 数字'0'不能单独解码(没有字母对应0)
  • 两位数组合必须在10-26之间才有效
  • 需要处理连续'0'和无效数字序列的情况

我在实际面试中多次遇到这个问题变形,发现90%的面试者都会在初始解法中遗漏至少一个边界条件。下面通过完整解法展示如何系统化处理这些陷阱。

2. 动态规划解法详解

2.1 状态定义与转移方程

我们定义dp[i]表示前i个字符的解码方式数。考虑最后一个字符的解码方式:

  1. 单独解码s[i](要求s[i] != '0'): dp[i] += dp[i-1]

  2. 组合解码s[i-1]和s[i](要求i>1且10<=s[i-1:i]<=26): dp[i] += dp[i-2]

初始条件:

  • dp[0] = 1(空字符串有1种解码方式)
  • dp[1] = 1(当s[0] != '0')
def numDecodings(s: str) -> int: if not s or s[0] == '0': return 0 n = len(s) dp = [0] * (n + 1) dp[0], dp[1] = 1, 1 for i in range(2, n + 1): # 处理单个字符 if s[i-1] != '0': dp[i] += dp[i-1] # 处理两个字符组合 two_digit = int(s[i-2:i]) if 10 <= two_digit <= 26: dp[i] += dp[i-2] return dp[n]

2.2 空间优化技巧

观察到dp[i]只依赖前两个状态,可以将空间复杂度从O(n)优化到O(1):

def numDecodings(s: str) -> int: if not s or s[0] == '0': return 0 prev1 = prev2 = 1 # dp[0]和dp[1] for i in range(1, len(s)): current = 0 if s[i] != '0': current += prev1 two_digit = int(s[i-1:i+1]) if 10 <= two_digit <= 26: current += prev2 prev2, prev1 = prev1, current return prev1

3. 边界条件处理实战

3.1 零值处理要点

零值是最容易出错的边界条件,需要特别注意:

  1. 字符串以'0'开头直接返回0(无法解码)
  2. 中间出现'0'时:
    • 必须与前一个字符组合('10'或'20'有效)
    • 其他组合(如'00','30')直接返回0

测试用例验证:

assert numDecodings("101") == 1 # 10,1 assert numDecodings("100") == 0 # 10,0无效 assert numDecodings("110") == 1 # 1,10 或 11,0(无效)

3.2 大数处理技巧

当字符串长度超过1000时,需要注意:

  1. Python无需处理整数溢出
  2. 其他语言可能需要模运算(如1e9+7)
  3. 实际面试中可以询问是否需要考虑大数情况

4. 算法复杂度分析

时间复杂度:

  • 单次遍历字符串:O(n)
  • 每个字符进行常数次操作

空间复杂度:

  • 基础解法:O(n)的dp数组
  • 优化解法:O(1)的滚动变量

5. 常见错误与调试技巧

5.1 典型错误模式

  1. 忽略前导零:

    # 错误实现示例 def wrong(s): if not s: return 0 dp = [0]*(len(s)+1) dp[0] = 1 # 缺少对s[0]=='0'的判断
  2. 无效组合判断不完整:

    # 错误示例:未检查两位数范围 if int(s[i-1:i]) > 0: # 应该检查10-26 dp[i] += dp[i-2]

5.2 调试建议

  1. 使用简单测试用例验证:

    • "" → 1
    • "0" → 0
    • "10" → 1
    • "27" → 1
  2. 打印dp数组检查中间状态:

    print(f"i={i}, s[i-1]={s[i-1]}, two_digit={two_digit}, dp={dp}")

6. 问题变种与扩展

6.1 输出所有解码方式

如果需要输出具体解码方案(而不仅是计数),可以使用回溯法:

def decodeWays(s): res = [] def backtrack(index, path): if index == len(s): res.append(''.join(path)) return if s[index] != '0': path.append(chr(ord('A') + int(s[index]) - 1)) backtrack(index + 1, path) path.pop() if index < len(s) - 1 and 10 <= int(s[index:index+2]) <= 26: path.append(chr(ord('A') + int(s[index:index+2]) - 1)) backtrack(index + 2, path) path.pop() backtrack(0, []) return res

6.2 编码方式变种

如果编码规则变化(如'A'->0),只需要修改:

  1. 零值处理逻辑
  2. 有效数字范围判断

7. 实际面试技巧

  1. 沟通策略:

    • 先说明暴力解法(递归+记忆化)
    • 再优化到动态规划
    • 最后讨论空间优化
  2. 测试用例设计:

    • 必须包含的测试案例:
      • 空字符串
      • 全零序列
      • 包含'0'的有效/无效组合
      • 最大值边界('26' vs '27')
  3. 代码书写规范:

    • 先处理边界条件
    • 变量命名清晰(prev1/prev2比a/b更好)
    • 添加必要注释

我在多次面试中验证,按照上述系统化的解题框架,可以在15分钟内完成从问题分析到完整代码的实现。记住动态规划类问题的通用解题步骤:

  1. 定义状态
  2. 建立转移方程
  3. 处理初始条件
  4. 考虑边界情况
  5. 优化空间复杂度

最后分享一个容易忽略的细节:当字符串长度为1时,直接返回1(如果非'0')而无需进入循环,这在优化解法中可以减少一次不必要的迭代。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 6:30:29

Kali Linux基础配置与安全优化指南

1. Kali Linux基础配置概述Kali Linux作为一款专为网络安全测试设计的Linux发行版&#xff0c;其基础配置是每位安全从业者的必修课。不同于普通Linux发行版&#xff0c;Kali默认集成了600多种安全工具&#xff0c;这决定了它在配置上有其特殊性。我在实际工作中发现&#xff0…

作者头像 李华
网站建设 2026/10/28 6:30:28

基于YOLOv8的实时犬种识别系统开发实践

1. 项目概述&#xff1a;当计算机视觉遇上宠物识别去年帮朋友开发犬舍管理系统时&#xff0c;发现人工记录犬种信息效率极低。传统方案要么依赖RFID芯片扫描&#xff0c;要么需要工作人员手动输入&#xff0c;不仅耗时还容易出错。于是我们用YOLOv8搭建了一套实时犬种识别系统&…

作者头像 李华
网站建设 2026/10/28 6:30:28

噪声注入技术揭示语言模型隐藏性能

1. 项目概述&#xff1a;噪声注入揭示语言模型的隐藏能力2025年NIPS会议上这项研究揭示了一个有趣现象&#xff1a;通过在特定层注入可控噪声&#xff0c;能够激发语言模型中"隐藏"的性能表现。这种现象被称为"Sandbagging"&#xff08;刻意保留实力&#…

作者头像 李华
网站建设 2026/10/28 6:29:17

面向对象编程核心原理与实战技巧

1. 面向对象编程的本质理解面向对象编程&#xff08;OOP&#xff09;不是简单的语法糖&#xff0c;而是一种思维方式的重构。我从业十年来见过太多开发者把类当作"有方法的字典"使用&#xff0c;这完全背离了OOP的初衷。真正的OOP应该像搭积木一样构建系统——每个类…

作者头像 李华
网站建设 2026/10/28 6:29:04

impeccable:专为浏览器扩展打造的契约式CLI工具

1. “impeccable”不是形容词&#xff0c;而是一个正在快速演进的开发者CLI工具你点开终端&#xff0c;输入npx impeccable&#xff0c;回车后看到的不是一句优雅的英文释义&#xff0c;而是一串带颜色的进度条、几行路径输出&#xff0c;最后弹出一个本地启动的Web界面——这正…

作者头像 李华
网站建设 2026/10/28 6:28:41

数字化门店与互动拍卖融合的创新零售模式解析

1. 树拍易购商业模式的核心逻辑树拍易购的创新之处在于将传统零售门店数字化升级与互动拍卖机制进行有机融合。这种模式打破了传统零售中"明码标价"的固定交易方式&#xff0c;通过引入拍卖元素为消费过程注入娱乐性和社交性。其底层商业逻辑可以拆解为三个关键维度&…

作者头像 李华