

91. 解码方法
题目链接: 91. 解码方法
题目叙述: 一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
“1” -> ‘A’
“2” -> ‘B’
…
“25” -> ‘Y’
“26” -> ‘Z’
然而,在解码已编码的消息时,你意识到有许多不同的方式来解码,因为有些编码被包含在其它编码当中(“2” 和 “5” 与 “25”)。
例如,11106可以映射为:
"AAJF" ,将消息分组为 (1, 1, 10, 6)
"KJF" ,将消息分组为 (11, 10, 6)
消息不能分组为 (1, 11, 06) ,因为 “06” 不是一个合法编码(只有 “6” 是合法的)。
注意,可能存在无法解码的字符串。
给你一个只含数字的 非空 字符串 s,请计算并返回 解码 方法的 总数 。如果没有合法的方式解码整个字符串,返回 0。
题目数据保证答案肯定是一个 32 位 的整数。
示例 1:
输入: s= “12”
输出: 2
解释: 它可以解码为 “AB”(1 2)或者 “L”(12)。
示例 2:
输入: s = “226”
输出: 3
解释: 它可以解码为 “BZ” (2 26), “VF” (22 6), 或者 “BBF” (2 2 6) 。
示例 3:
输入: s = “06”
输出: 0
解释: “06” 无法映射到 “F” ,因为存在前导零(“6” 和 “06” 并不等价)。
提示:
1 <=s.length<= 100
s 只包含数字,并且可能包含前导零。
💦 前提注意: 这道题的s是一个非空字符串,而不是数组,所以计算时应减去'0'
解题思路:
- 状态表示
dp[i]表示:以i位置为结尾时,所有解码方法的总数 - 状态转移方程
根据最近的一步,划分问题

其中a表示s[i]位置的数,b表示s[i-1]位置的数
dp[i] = dp[i-1] + dp[i-2] - 初始化
保证填表时不越界
以0位置结尾时说明此时只解码了一个字符

以1位置结尾时说明此时解码了两个字符

- 填表顺序
从左向右 - 返回值
dp[n-1]
代码实现:
class Solution {
public:
int numDecodings(string s) {
//创建dp表
//初始化
//填表
//返回值
int n = s.size();
vector<int> dp(n);
dp[0] = s[0] != '0';
//处理边界条件
if (n == 1) return dp[0];
if (s[0] != '0' && s[1] != '0') dp[1] += 1;//第一个位置能单独解码,并且第二个位置也能单独解码
int t = (s[0] - '0') * 10 + s[1] - '0';//前两个位置所表示的数
if (t >= 10 && t <= 26) dp[1] += 1;
for (int i = 2; i < n; i++)
{
if (s[i] != '0') dp[i] += dp[i - 1];//处理单独解码的情况
int t = (s[i - 1] - '0') * 10 + s[i] - '0';//第二种情况所对应的数
if (t >= 10 && t <= 26) dp[i] += dp[i - 2];
}
return dp[n - 1];
}
细节优化:
处理边界问题以及初始化问题的技巧
- 我们可以开一个比旧的表多1个的新的
dp表,使得旧dp表下标为0的位置,映射到新的dp表下标为1的位置,旧的下标为1的位置映射到新的下标为2的位置…依次类推。

- 这样以来
dp[i]就可以表示为以第i个字符为终点的解码方法的个数。所以就只需要初始化第1的字符即可。 - 这里有个小细节,我们在初始化
dp[0]这个虚拟节点时要将它初始化成1,比如只有两个字符我们要判断时 ,第二个字符单独解码时的方法数为1,第二个字符与第一个字符共同解码时的方法总数应该为2,dp[2] = dp[1] + dp[0],我们可以将dp[0]给反推出来,所以dp[0]应该初始化为1

代码实现:
class Solution {
public:
int numDecodings(string s) {
//创建dp表
//初始化
//填表
//返回值
int n = s.size();
//创建dp表
vector<int> dp(n+1);
dp[0] = 1;
dp[1] = s[0] != '0';
for(int i = 2;i <= n;i++)
{
if(s[i-1] != '0') dp[i]+=dp[i-1];
int b = 10*(s[i-2]-'0') + (s[i -1] - '0');
if(b>=10 && b <= 26) dp[i]+=dp[i- 2];
}
return dp[n];
}
};






![[贪心算法]买卖股票的最佳时机 买卖股票的最佳时机Ⅱ K次取反后最大化的数组和 按身高排序 优势洗牌(田忌赛马)](https://i-blog.csdnimg.cn/direct/df8b476b697e433f8778c2d7ea1ea0c6.png)










