题目描述
一条包含字母 A-Z 的消息通过以下映射进行了编码:
1 | "1" -> 'A' |
然而,在解码已编码的消息时,你意识到有许多不同的方式来解码,因为有些编码被包含在其它编码当中("2" 和 "5" 与 "25")。
例如,"11106" 可以映射为:
"AAJF",将消息分组为(1, 1, 10, 6)"KJF",将消息分组为(11, 10, 6)
消息不能分组为 (1, 11, 06),因为 "06" 不是一个合法编码(只有 "6" 是合法的)。
注意,可能存在无法解码的字符串。
给你一个只含数字的非空字符串 s,请计算并返回解码方法的总数。如果没有合法的方式解码整个字符串,返回 0。
题目数据保证答案肯定是一个 32 位的整数。
示例
示例 1:
1 | 输入:s = "12" |
示例 2:
1 | 输入:s = "226" |
示例 3:
1 | 输入:s = "06" |
提示
1 <= s.length <= 100s只包含数字,并且可能包含前导零
解题思路
这是一道经典的动态规划问题。
核心思想
定义 dp[i] 表示:字符串 s[0:i](即前 i 个字符)的解码方法总数。
我们需要分析每一步的状态转移。
状态分析
单个字符解码:如果
s[i-1]不是'0',则它可以单独解码为一个字母
$$dp[i] += dp[i-1]$$两个字符组合解码:如果
s[i-2:i]形成的两位数在 10 到 26 之间,则可以组合解码
$$dp[i] += dp[i-2]$$
特殊情况
'0'字符不能单独解码,必须与前一个字符组合- 前导零
"0x"(x 为数字)是无效的
遍历顺序
从左到右遍历字符串,确保在计算 dp[i] 时,dp[i-1] 和 dp[i-2] 已经计算完成。
代码实现
1 | class Solution: |