news 2026/5/17 4:51:13

动态规划解决 Decode Ways 问题:从理解到实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动态规划解决 Decode Ways 问题:从理解到实现

题目与直观理解

题目给了一段只包含数字的字符串 s,每个数字序列可以通过下面的映射解码成字母:

“1” -> ‘A’,“2” -> ‘B’,…,“25” -> ‘Y’,“26” -> ‘Z’。

比如 “12” 可以解码为 “AB”(1,2)或 “L”(12),所以答案是 2。

但像 “06” 这种因为有前导 0,不能解码成 ‘F’,此时整串无效,返回 0。

问题:给定 s,返回不同解码方式的总数,如果完全无法解码,则返回 0。

LeetCode原题链接

动态规划建模

这类"前缀 + 计数"的问题,非常适合用一维 DP 来建模。

状态定义:设 dp[i] 表示前 i 个字符(s[0…i-1])的解码总数。

数组大小:字符串长度为 str_len,则 dp 的下标范围是 0…str_len,一共 str_len + 1 个元素。

基础状态:dp[0] = 1,表示空字符串有 1 种"什么都不选"的解码方式,这是后续转移的起点。

有了定义之后,目标就是返回 dp[str_len],即整个字符串的解码数。

转移方程设计

每次处理到第 i 个字符(1-based),看两种可能的"最后一段":一位数或两位数。

一位数结尾

取出当前一位:digit_1 = s[i-1] - ‘0’。

如果 1 <= digit_1 <= 9,说明这一位可以单独映射成一个字母,就可以从 dp[i-1] 转移过来:

dp[i] += dp[i-1]

注意:digit_1 为 0 时无效,不能单独解码,所以这一分支要跳过。

两位数结尾

i 至少要大于 1,才能看两位:i > 1。

取出两位数:digit_2 = (s[i-2]-‘0’) * 10 + (s[i-1]-‘0’)。

如果 10 <= digit_2 <= 26,说明这两位可以一起映射成一个字母,就可以从 dp[i-2] 转移过来:

dp[i] += dp[i-2]

这里自然规避了前导 0:比如 “06” 转出来就是 6,不在 10~26 中,所以两位分支也不会被加上。

这样的转移有两个关键点:

  • 使用"+=“而不是”=",因为可能同时存在"一位结尾"和"两位结尾"两种方案,需要累加。
  • 0 的处理是通过判断区间来隐式完成的:一位需要 1~9,两位需要 10~26。

边界与特例思考

实现前要先想清楚几个典型用例:

s = “12”:

  • dp[0] = 1。
  • i=1: digit_1=1 → dp[1]+=dp[0]=1。
  • i=2: digit_1=2 → dp[2]+=dp[1]=1;digit_2=12 → dp[2]+=dp[0]=1,总共 2。

s = “226”:

答案为 3,分别是 “2 2 6”、“22 6” 和 “2 26”。

s = “06”:

  • i=1: digit_1=0,不在 1~9,dp[1] 仍为 0。
  • i=2: digit_1=6 → dp[2]+=dp[1]=0;digit_2=6,不在 10~26,dp[2] 还是 0,最终返回 0。

另外还要考虑:

  • 字符串为空或指针为 NULL 时,直接返回 0,防止非法输入。
  • 动态申请 dp 数组后要记得初始化为 0,并在最后释放内存。

完整 C 代码实现

下面是最终通过所有用例、时间 0ms 的 C 语言实现,时间复杂度 O(n),空间复杂度 O(n):

intnumDecodings(char*s){inti,str_len,digit_1,digit_2,result;int*dp;if(s==NULL||strlen(s)==0)return0;str_len=strlen(s);dp=(int*)malloc((str_len+1)*sizeof(int));memset(dp,0,(str_len+1)*sizeof(int));dp[0]=1;for(i=1;i<=str_len;i++){digit_1=s[i-1]-'0';if(digit_1>=1&&digit_1<=9)dp[i]+=dp[i-1];if(i>1){digit_2=(s[i-2]-'0')*10+(s[i-1]-'0');if(digit_2>=10&&digit_2<=26)dp[i]+=dp[i-2];}}result=dp[str_len];free(dp);returnresult;}

这套写法的核心是:

  • 用 dp[i] 表达"前 i 个字符"的解码数量。
  • 通过"1 位 + 2 位"两种选择进行转移,配合区间判断自然处理 0 和前导 0。
  • 基础状态 dp[0]=1 保证空串为 1 种方式,使得 i=1、2 的转移都成立。

这道题和「爬楼梯」「斐波那契」在递推形式上非常相似,只是多了数字合法性和 0 的边界判断,是入门字符串 DP 的一个很好的练习。

相关链接

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

Tweepy PKCE安全认证终极指南:零风险客户端授权实战

Tweepy PKCE安全认证终极指南&#xff1a;零风险客户端授权实战 【免费下载链接】tweepy tweepy/tweepy: Tweepy 是一个 Python 库&#xff0c;用于访问 Twitter API&#xff0c;使得在 Python 应用程序中集成 Twitter 功能变得容易。 项目地址: https://gitcode.com/gh_mirr…

作者头像 李华
网站建设 2026/5/7 23:01:31

[特殊字符]️ 挽救错误提交:Linux 内核开发中的“后悔药”

在软件开发的世界里&#xff0c;尤其是在Linux内核这种庞大且复杂的项目中&#xff0c;犯错是难免的。你可能刚刚提交了一段代码&#xff0c;结果CI&#xff08;持续集成&#xff09;系统立刻报错&#xff0c;或者更糟糕的是&#xff0c;你的提交导致了系统崩溃&#xff08;Ker…

作者头像 李华
网站建设 2026/5/8 20:48:37

TensorLayer实战指南:2025年文本纠错模型的五大突破性应用

TensorLayer实战指南&#xff1a;2025年文本纠错模型的五大突破性应用 【免费下载链接】TensorLayer Deep Learning and Reinforcement Learning Library for Scientists and Engineers 项目地址: https://gitcode.com/gh_mirrors/te/TensorLayer 在人工智能快速发展的…

作者头像 李华
网站建设 2026/5/13 20:42:22

vLLM 巨大里程碑

vLLM 巨大里程碑 原创 老章很忙 Ai学习的老章 2026年1月6日 17:02 中国香港 我是 vLLM 的粉丝&#xff0c;更新过 N 多相关文章&#xff0c;内网部署大模型全都是使用 vLLM 大模型本地部署&#xff0c;vLLM 睡眠模式来了 vLLM v0.13.0 来了&#xff0c;对 DeepSeek 深度优…

作者头像 李华
网站建设 2026/5/1 20:32:41

ms-swift支持模型推理延迟SLA保障服务质量

ms-swift支持模型推理延迟SLA保障服务质量 在企业级AI应用日益普及的今天&#xff0c;一个关键问题逐渐浮现&#xff1a;我们能否像对待传统数据库或API服务那样&#xff0c;为大语言模型&#xff08;LLM&#xff09;的服务质量提供可量化的承诺&#xff1f;尤其是在智能客服、…

作者头像 李华
网站建设 2026/5/5 21:09:11

Statsviz:实时监控Go程序运行时指标的利器

Statsviz&#xff1a;实时监控Go程序运行时指标的利器 【免费下载链接】statsviz &#x1f680; Visualise your Go program runtime metrics in real time in the browser 项目地址: https://gitcode.com/gh_mirrors/st/statsviz 项目介绍 Statsviz是一个强大的开源工…

作者头像 李华