LeetCode - 91. Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.
Input: “12” Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).
Input: “226” Output: 3
Explanation: It could be decoded as “BZ” (2 26), “VF” (22 6), or “BBF” (2 2 6).
实际面试遇到了,当时想错了- -,出了门就发现写错了。。
这道题其实不麻烦,就是在遍历到一个位置 i 的时候,知道前边这个位置 i - 1 为结尾的情况数 pre1,以及 i - 2 位置为结尾的情况数 pre2。那么,当 i 位置不是 0 的时候,自己一个数组成一个字符的情况就是 pre1 种;如果 i 位置是0,那么前边的数只能是 1 或者 2 不然这个 string 就是不合法的,直接返回 0。对于 i - 1 位置和 i 位置组成一个合法字符,也就是 10、11、12 … 19、20、21、22、23、24、25、26 这些情况,a == '1' || (a == '2' && b <= '6')
,i 位置情况就要再加上 pre2 即可。每次更新 pre1 之后让 pre2 = 之前的pre1 即可。
bool isValid(char a, char b) {
return a == '1' || (a == '2' && b <= '6');
}
int numDecodings(string s) {
const int len = s.length();
if (s[0] == '0') return 0;
if (len == 1) return 1;
// pre1: 前一个位置为结尾的情况, pre2: 前两个位置为结尾的情况
int pre1 = 1, pre2 = 1;
for(int i = 1; i < len; ++i) {
const int pre1_cpy = pre1;
if (s[i] == '0') {
if(!isValid(s[i - 1], s[i]))
return 0;
pre1 = 0;
}
if (isValid(s[i - 1], s[i])) pre1 += pre2;
pre2 = pre1_cpy;
}
return pre1;
}
用个一位数组dp也可以:
bool isValid(char a, char b) {
return a == '1' || (a == '2' && b <= '6');
}
int numDecodings(string s) {
const int n = s.length();
if(n == 0) return 0;
if(s[0] == '0') return 0;
if(n == 1) return 1;
vector<int> dp(n + 1, 0);
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i <= n; ++i) {
if(s[i - 1] == '0') {
if(s[i - 2] != '1' && s[i - 2] != '2')
return 0;
dp[i] = dp[i - 2];
}
else {
dp[i] = dp[i - 1];
if(isValid(s[i - 2], s[i - 1]))
dp[i] += dp[i - 2];
}
}
return dp[n];
}
LeetCode - 639. Decode Ways II
A message containing letters from A-Z is being encoded to numbers using the following mapping way:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
Beyond that, now the encoded string can also contain the character ‘*’, which can be treated as one of the numbers from 1 to 9.
Given the encoded message containing digits and the character ‘*’, return the total number of ways to decode it.
Also, since the answer may be very large, you should return the output mod 109 + 7.
Example 1: Input: “*” Output: 9
Explanation: The encoded message can be decoded to the string: “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”.
Example 2: Input: “1*” Output: 9 + 9 = 18
比上边的题多了个 '*'
,就是能够表示 1-9 的任意数。问能有多少种 decode 可能(这道题实际面试没有遇到过,但是也一起总结了)。
其实就是比上边的要讨论的情况多一些,不过也是每次记录 pre1,更新 pre1,用保存起来的原始 pre1 更新 pre2。
int numDecodings(string s) {
if (s.empty() || s[0] == '0') return 0;
const int MOD = 1000000007;
long long pre1 = s[0] == '*' ? 9 : 1, pre2 = 1;
for(size_t i = 1; i < s.length(); ++i) {
const auto pre1_cpy = pre1; // 保存为后边修改 m2 = m1;
if(s[i] == '*') {
pre1 *= 9; // '*' 表示 1-9
if (s[i - 1] == '1')
pre1 = (pre1 + 9 * pre2) % MOD; // 11~19
else if(s[i - 1] == '2')
pre1 = (pre1 + 6 * pre2) % MOD; // 21~26
else if (s[i - 1] == '*')
pre1 = (pre1 + 15 * pre2) % MOD; // 9 + 6 = 15
}
else {
if (s[i] == '0')
pre1 = 0;
if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] <= '6'))
pre1 = (pre1 + pre2) % MOD;
else if (s[i - 1] == '*')
pre1 = (pre1 + (s[i] <= '6' ? 2 : 1) * pre2) % MOD;
}
pre2 = pre1_cpy;
}
return pre1;
}