题目描述:

一条包含字母 A-Z 的消息通过以下方式进行了编码:

'A' -> 1
'B' -> 2
...
'Z' -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 1:

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

示例 2:

输入:s = "0"
输出:0

分析:

  因为 s[0:i] 的解码方案 可以由 s[0:i-1] 的解码方案 和 s[i] 的值推导得到

所以 可以使用动态规划算法解决。下面具体分析:

  给定 数字字符串 "1226" ,去掉最后一位得到子串 "122"  ,"122" 可解码

为 1,2,2   12,2   1,22   三种,"1226"的解码方案 是将字符 '6' 加到 "122"的所有解码方案中

对1,2,2 生成"1226"的解码序列 有两种选择,'6' 单独作一位加在后面  1,2,2,6

或 '6' 和 最后一位2拼接成  1,2,26 。由 "122"的解码方案 生成 "1226"的解码方案有

1,2,2,6   1,2,26  12,2,6  12,26   1,22,6

即可以根据 s[0:i-1] 的解码方案 和 s[i] 的值推出 s[0:i] 的解码方案。需要特别考虑 s[i-1] 和 s[i] 为 '0' 的情况。

1. 定义状态   dp[i] :s[0 : i]  的所有解码, np[i] s[0 : i]  的所有解码中,最后一个编码是1位的解码,如 对 "122"

的解码  1,2,2   12,2   1,22     dp[2] =  3 ,np[2] = 2 。

状态转移和 状态空间压缩 见下面代码和注释:

 1 class Solution {
2 public:
3 int numDecodings(string s)
4 {
5 int dp ;
6 int np ;
7 //base case
8 if(s[0] == '0'){
9 dp = 0;
10 np = 0;
11 }
12 else
13 {
14 dp = 1;
15 np = 1;
16 }
17 //state move
18 for(int i = 1;i < s.size();++i)
19 {
20 if(s[i-1] == '0')//s[0:i-1] 有效的结尾只可能是 10,20,
21 {
22 if(s[i] == '0') //‘0’ 既不能拼接在 10,20 后面,也 单独作一位
23 {
24 dp = 0;
25 np = 0;
26 }
27 //非‘0’ 可以单独作一位
28 else
29 {
30 if(dp > 0)//单独作一位跟在 ‘10’ ‘20’ 后面
31 {
32 // dp = dp;
33 np = dp;
34 }
35 else//s[0:i-1] 没有合法的解码方法
36 {
37 dp = 0;
38 np = 0;
39 }
40 }
41 }
42 else if(s[i] == '0') // s[i-1] != '0' ,s[i] == '0'
43 // s[i] == '0' 只能在 s[i-1]是 1或2 的时候与之拼接成‘10’或’20‘,不能在其他情况下拼接,也不能单独作一位
44 {
45 if(s[i-1] == '1' || s[i-1] == '2') //s[i-1]是 1或2 的时候与之拼接成‘10’或’20‘
46 {
47 dp = np;
48 np = 0;
49 }
50 else
51 {
52 dp = 0;
53 np = 0;
54 }
55 }
56 //s[i]和s[0:i-1]的所有解码序列 即可拼接又可单独作一位
57 else if(s[i-1] == '1' || (s[i-1] == '2' && s[i] >= '1' && s[i] <= '6'))
58 {
59 int temp = dp;
60 dp = dp + np;
61 np = np + (temp - np);
62 }
63 // s[i-1] 不是 0,1,2 s[i] 不是0,s[i]只能单独作一位
64 else
65 {//dp 不变 所有的s[0:i-1]的 2位结尾的解码,全部都变成 1位结尾的解码,1位结尾的解码依然是一位结尾的解码
66 // dp = dp;
67 np = dp;
68 }
69 }
70 return dp;
71 }
72 };

最新文章

  1. DM9000驱动移植在mini2440(linux2.6.29)和FS4412(linux3.14.78)上的实现(deep dive)篇一
  2. imx6 关闭调试串口
  3. 缓存篇~第六回 Microsoft.Practices.EnterpriseLibrary.Caching实现基于方法签名的数据集缓存
  4. 某篇ctr预估ppt的链接
  5. PHP多线程
  6. Cookie与Session详解
  7. IOS6 字体高亮显示
  8. Css3案例
  9. 基于visual Studio2013解决C语言竞赛题之1041反向打印
  10. CentOS 6.5 GIT 服务器搭建
  11. Java中执行shell笔记
  12. vue-cli 脚手架 安装
  13. 构建微服务开发环境4————安装Docker及下载常用镜像
  14. No Java compiler available
  15. BASH 基本语法
  16. Linux 如何测试 IO 性能(磁盘读写速度)
  17. POJ 2864
  18. 【GIS】Cesium1.49编译
  19. pixi.js 总结
  20. 浅谈JS作用域和闭包

热门文章

  1. Git命令diff格式详解
  2. TMS, XYZ &amp; WMTS的不同
  3. 50种编程语言,一句 “Hello, World”!展现编程语言七十年发展!
  4. spring boot:方法中使用try...catch导致@Transactional事务无效的解决(spring boot 2.3.4)
  5. jdk、eclipse和idea安装
  6. Cypress系列(67)- 环境变量设置指南
  7. 在VMware虚拟机Ubuntu使用traceroute
  8. 【API管理 APIM】如何查看APIM中的Request与Response详细信息,如Header,Body中的参数内容
  9. 利用Gitee转接GitHub下载加速 简简单单 - 快快乐乐
  10. Moment.js常见用法总结