news 2026/9/6 17:56:32

动态规划解决 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/9/2 14:13:06

哭死,卡了一下午的报错终于又解决了

安装opencv-python模块时&#xff0c;发现pip install opencv-python命令不管用了 一开始问题如下&#xff1a; WARNING: Failed to activate VS environment: Could not find C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe 试了下解决方案是安装 …

作者头像 李华
网站建设 2026/9/3 1:13:40

突破性性能优化:掌握Kryo框架的数据读写艺术

突破性性能优化&#xff1a;掌握Kryo框架的数据读写艺术 【免费下载链接】kryo Java binary serialization and cloning: fast, efficient, automatic 项目地址: https://gitcode.com/gh_mirrors/kr/kryo 在Java高性能序列化领域&#xff0c;Kryo框架凭借其卓越的数据读…

作者头像 李华
网站建设 2026/9/5 13:38:12

CreamApi终极指南:快速解锁三大游戏平台DLC完整内容

CreamApi终极指南&#xff1a;快速解锁三大游戏平台DLC完整内容 【免费下载链接】CreamApi 项目地址: https://gitcode.com/gh_mirrors/cr/CreamApi CreamApi是一款功能强大的开源工具&#xff0c;专为游戏玩家设计&#xff0c;能够智能解锁Steam、Epic Games Store和U…

作者头像 李华
网站建设 2026/9/3 1:13:46

ER-Save-Editor终极指南:轻松打造你的完美艾尔登法环存档

ER-Save-Editor终极指南&#xff1a;轻松打造你的完美艾尔登法环存档 【免费下载链接】ER-Save-Editor Elden Ring Save Editor. Compatible with PC and Playstation saves. 项目地址: https://gitcode.com/GitHub_Trending/er/ER-Save-Editor 还在为艾尔登法环中反复刷…

作者头像 李华
网站建设 2026/9/3 1:15:32

Crypto++开源密码库终极指南:企业安全开发实战手册

Crypto开源密码库终极指南&#xff1a;企业安全开发实战手册 【免费下载链接】cryptopp free C class library of cryptographic schemes 项目地址: https://gitcode.com/gh_mirrors/cr/cryptopp 在当今数字化时代&#xff0c;数据安全已成为企业发展的生命线。Crypto作…

作者头像 李华
网站建设 2026/9/3 1:13:46

微信智能助手部署指南:解决消息回复难题的技术方案

微信智能助手部署指南&#xff1a;解决消息回复难题的技术方案 【免费下载链接】wechat-bot &#x1f916;一个基于 WeChaty 结合 DeepSeek / ChatGPT / Kimi / 讯飞等Ai服务实现的微信机器人 &#xff0c;可以用来帮助你自动回复微信消息&#xff0c;或者管理微信群/好友&…

作者头像 李华