leetcode:91. 解码方法
题目
一条包含字母 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 位 的整数。
示例:
输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。
输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
输入:s = "0"
输出:0
解释:没有字符映射到以 0 开头的数字。
含有 0 的有效映射是 'J' -> "10" 和 'T'-> "20" 。
由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。
解答 & 代码
解法一:动态规划
动态规划:
- 动态规划数组
**dp**
:dp[i]
代表前i
个字符s[0,...,i-1]
的解码方式数量 - 状态转移方程:
**dp[i] = 0 + val1 + val2**
- 若单个数字
s[i-1]
本身可以解码为一个字母,则val1 = dp[i-1]
,否则val1 = 0
- 若两个数字
s[i-2] s[i-1]
可以解码为一个字母,则val2 = dp[i-2]
,否则val2 = 0
- 若单个数字
初始化:
dp[0] = 1
dp[1] = (s[0] >= '1' && s[0] <= '9') ? 1 : 0
复杂度分析:设字符串长为 Nclass Solution { public: int numDecodings(string s) { int len = s.size(); // 动态规划数组 dp:dp[i] 代表前 i 个字符 s[0,...,i-1] 的解码方式数量 vector<int> dp(len + 1, 0); dp[0] = 1; dp[1] = (s[0] >= '1' && s[0] <= '9') ? 1 : 0; for(int i = 2; i <= len; ++i) { // 若单个数字 s[i-1] 本身可以解码为一个字母 if(s[i - 1] >= '1' && s[i - 1] <= '9') dp[i] += dp[i - 1]; // 若两个数字 s[i-2] s[i-1] 可以解码为一个字母 if((s[i - 2] == '1' && s[i - 1] >= '0' && s[i - 1] <= '9') || (s[i - 2] == '2' && s[i - 1] >= '0' && s[i - 1] <= '6')) dp[i] += dp[i - 2]; } return dp[len]; } };
时间复杂度 O(N):
- 空间复杂度 O(N):
执行结果:
执行结果:通过
执行用时:4 ms, 在所有 C++ 提交中击败了 14.08% 的用户
内存消耗:6.1 MB, 在所有 C++ 提交中击败了 30.57% 的用户
解法二:状态压缩
上面的动态规划状态 dp[i]
只和 dp[i-2]
、dp[i-1]
有关,因此可以不用 dp 数组,只设置几个变量即可
class Solution {
public:
int numDecodings(string s) {
int len = s.size();
int dpi2 = 1; // dp[i-2],初始化为 dp[0]
int dpi1 = (s[0] >= '1' && s[0] <= '9') ? 1 : 0; // dp[i-1], 初始化为 dp[1]
int dpi = dpi1; // dp[i]
for(int i = 1; i < len; ++i)
{
dpi = 0;
if(s[i] >= '1' && s[i] <= '9')
dpi += dpi1;
if((s[i - 1] == '1' && s[i] >= '0' && s[i] <= '9') ||
(s[i - 1] == '2' && s[i] >= '0' && s[i] <= '6'))
dpi += dpi2;
dpi2 = dpi1;
dpi1 = dpi;
}
return dpi;
}
};
复杂度分析:设字符串长为 N
- 时间复杂度 O(N):
- 空间复杂度 O(1):
执行结果:
执行结果:通过
执行用时:0 ms, 在所有 C++ 提交中击败了 100.00% 的用户
内存消耗:5.9 MB, 在所有 C++ 提交中击败了 96.18% 的用户