题目描述(题目链接)
一条包含字母 A-Z 的消息通过以下映射进行了编码:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
要解码已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母,可能有多种方法。例如:
“11106” 可以映射为:
“AAJF” ,将消息分组为 (1 1 10 6)
“KJF” ,将消息分组为 (11 10 6)
注意,消息不能分组为 (1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。
给你一个只含数字的 非空 字符串 s ,请计算并返回解码方法的总数 。
题目数据保证答案肯定是一个 32 位 的整数。
求解思路
动态规划思想:
存储结构: dp[i]表示到第i个字符的解码方法总数
状态转移: dp[i]从以下两种方式得到:
- 从i-2过来,只用考虑字符串s(i-1,i)能不能被解码,若能,dp[i] += dp[i-2]
- 从i-1过来,只用考虑字符串s[i]能不能被解码,若能,dp[i] += dp[i-1]
初始化:
- 把数组dp的所有元素初始化为0
- 初始化dp[0],dp[1]
边界情况检查:
- 数组长度为1时,不能初始化dp[1],直接返回
- 每一处方法数为0时,说明有不能解码的字符,直接返回
代码
class Solution {
public:
int numDecodings(string s) {
int len = s.size();
int dp[len];
for(int i=0;i<len;i++){
dp[i] = 0; //都初始化为0
}
//初始化0
if(s[0]>='1'&&s[0]<='9') dp[0] = 1;
else dp[0] = 0;
if(len==1||dp[0]==0) return dp[0]; //边界情况,数组长度为1或第0个字符的方法数为0
//初始化1
if(s[1]>='1'&&s[1]<='9') dp[1] += dp[0];
if(s.substr(0,2)>="10"&&s.substr(0,2)<="26") dp[1]++;
if(dp[1]==0) return 0; //边界情况,方法数为0说明有不能解码的字符,直接返回
for(int i=2;i<len;i++){
if(s.substr(i-1,2)>="10"&&s.substr(i-1,2)<="26") dp[i] += dp[i-2]; //状态转移 从i-2过来
if(s[i]>='1'&&s[i]<='9') dp[i] += dp[i-1]; //状态转移 从i-1过来
if(dp[i]==0) return 0; //边界情况,方法数为0说明有不能解码的字符,直接返回
}
return dp[len-1];
}
};