news 2026/4/23 17:37:29

动态规划解决 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/4/22 3:06:51

3分钟搞定!Element UI Table组件数据报表快速生成全攻略

3分钟搞定&#xff01;Element UI Table组件数据报表快速生成全攻略 【免费下载链接】element A Vue.js 2.0 UI Toolkit for Web 项目地址: https://gitcode.com/gh_mirrors/eleme/element 还在为复杂的数据报表制作而头疼吗&#xff1f;Element UI Table组件让你轻松实…

作者头像 李华
网站建设 2026/4/23 8:16:04

OpenLLaMA营销文案生成实战:5步打造高效AI创作流程

OpenLLaMA营销文案生成实战&#xff1a;5步打造高效AI创作流程 【免费下载链接】open_llama OpenLLaMA, a permissively licensed open source reproduction of Meta AI’s LLaMA 7B trained on the RedPajama dataset 项目地址: https://gitcode.com/gh_mirrors/op/open_lla…

作者头像 李华
网站建设 2026/4/17 1:15:08

PyModbus安装与配置完整指南

PyModbus安装与配置完整指南 【免费下载链接】pymodbus A full modbus protocol written in python 项目地址: https://gitcode.com/gh_mirrors/py/pymodbus PyModbus是一个用Python编写的完整Modbus协议实现&#xff0c;它为工业自动化系统提供了强大的通信能力。无论您…

作者头像 李华
网站建设 2026/4/18 6:54:48

鸿蒙远程投屏实战秘籍:跨设备控制的终极解决方案

鸿蒙远程投屏实战秘籍&#xff1a;跨设备控制的终极解决方案 【免费下载链接】鸿蒙远程真机工具 该工具主要提供鸿蒙系统下基于视频流的投屏功能&#xff0c;帧率基本持平真机帧率&#xff0c;达到远程真机的效果。 项目地址: https://gitcode.com/OpenHarmonyToolkitsPlaza/…

作者头像 李华
网站建设 2026/4/19 18:57:02

NocoBase数据可视化实战:5大场景解析与零代码报表构建指南

NocoBase数据可视化实战&#xff1a;5大场景解析与零代码报表构建指南 【免费下载链接】nocobase 极易扩展的无代码/低代码开发平台。NocoBase is a scalability-first, open-source no-code/low-code platform to build internal tools. 项目地址: https://gitcode.com/Git…

作者头像 李华
网站建设 2026/4/21 23:48:39

SAPlink终极指南:10分钟掌握SAP开发对象迁移神器

SAPlink终极指南&#xff1a;10分钟掌握SAP开发对象迁移神器 【免费下载链接】SAPlink SAPlink 项目地址: https://gitcode.com/gh_mirrors/sa/SAPlink 在SAP Netweaver系统的ABAP开发领域&#xff0c;SAPlink作为一款革命性的导入导出工具&#xff0c;彻底改变了传统SA…

作者头像 李华