LeetCode 91. 解码方法(动态规划、DP、DP、多写多练 )
作者:互联网
91. 解码方法
一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
'A' -> 1
'B' -> 2
...
'Z' -> 26
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“111” 可以将 “1” 中的每个 “1” 映射为 “A” ,从而得到 “AAA” ,或者可以将 “11” 和 “1”(分别为 “K” 和 “A” )映射为 “KA” 。注意,“06” 不能映射为 “F” ,因为 “6” 和 “06” 不同。
给你一个只含数字的 非空 字符串 num ,请计算并返回 解码 方法的 总数 。
题目数据保证答案肯定是一个 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 = "0"
输出:0
解释:没有字符映射到以 0 开头的数字。含有 0 的有效映射是 'J' -> "10" 和 'T'-> "20" 。由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。
示例 4:
输入:s = "06"
输出:0
解释:"06" 不能映射到 "F" ,因为字符串开头的 0 无法指向一个有效的字符。
提示:
1 <= s.length <= 100
s 只包含数字,并且可能包含前导零。
通过次数84,792提交次数331,690
分析
显然这道题目是动态规划的问题,如果做过类似的问题,就很容易想出解法(没想出来),假设我们遍历到了 s[i]
,那么我们可以将 s[i]
当作一位或将 s[i-1],s[i]
当作两位来进行译码,那么有如下两个条件:
(1)将s[i]
当作一位来译码,那么必须满足 '1'<=s[i]<='9'
(2)将s[i-1],s[]i]
当作两位来译码,那么必须满足s[i-1]和s[i]组成的两位数在10——26之间
也就是: 10<=(s[i-1] - '0') * 10 + s[i] - '0' <= 26
那么状态转移方程为:
f
[
i
]
=
f
[
i
−
1
]
(
若
满
足
一
位
译
码
条
件
)
+
f
[
i
−
2
]
(
若
满
足
两
位
译
码
条
件
)
f[i] = f[i-1](若满足一位译码条件) + f[i-2](若满足两位译码条件)
f[i]=f[i−1](若满足一位译码条件)+f[i−2](若满足两位译码条件)
动态规划分析如下图:
class Solution {
public:
int numDecodings(string s) {
int n = s.size();
s = ' ' + s; // 下标从1开始
vector<int> f(n + 1);
f[0] = 1;
for(int i = 1; i <= n; i++)
{
if(s[i] >= '1' && s[i] <= '9') f[i] += f[i-1]; // 满足一位译码
if(i > 1) // 满足两位译码,至少要两位
{
int t = (s[i-1] - '0') * 10 + s[i] - '0';
if(t >= 10 && t <= 26) f[i] += f[i-2];
}
}
return f[n];
}
};
标签:10,06,映射,示例,解码,多练,译码,多写,DP 来源: https://blog.csdn.net/qq_45260619/article/details/113813899