问题
Decode Ways Medium
A message containing letters from A-Z can be encoded into numbers using the following mapping:
'A' -> "1"
'B' -> "2"
...
'Z' -> "26"
To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, "11106" can be mapped into:
"AAJF"with the grouping(1 1 10 6)"KJF"with the grouping(11 10 6)
Note that the grouping (1 11 06) is invalid because "06" cannot be mapped into 'F' since "6" is different from "06".
Given a string s containing only digits, return the number of ways to decode it.
The answer is guaranteed to fit in a 32-bit integer.
Example 1:
Input: s = "12"
Output: 2
Explanation: "12" could be decoded as "AB" (1 2) or "L" (12).
Example 2:
Input: s = "226"
Output: 3
Explanation: "226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
Example 3:
Input: s = "0"
Output: 0
Explanation: There is no character that is mapped to a number starting with 0.
The only valid mappings with 0 are 'J' -> "10" and 'T' -> "20", neither of which start with 0.
Hence, there are no valid ways to decode this since all digits need to be mapped.
Example 4:
Input: s = "06"
Output: 0
Explanation: "06" cannot be mapped to "F" because of the leading zero ("6" is different from "06").
Constraints:
1 <= s.length <= 100scontains only digits and may contain leading zero(s).
解题思路
本题要求计算可行的解码的方法有多少,是一个典型的最优子结构问题,可以用动态规划获得最优解法。
我们定义为字符串s中的子字符串s(0,i)的解码方法数。那么本题的最终解就是,n为字符串s的长度。接下来就需要推导状态转移方程,比如,将一个复杂的问题分解为子问题,然后递归求解。
我们先分析一个特殊的编码0。首先0不可以单独表示一个字母,如果s的第一个编码是0,则不可以被解码。其次0只能和前面的1或者2组合起来表示一个字母,只有一种可能性,所以如果s[i] == 0且s[i-1] in (1,2),那么。
当s[i]不为0时(假设编码为y),它有可能可以和前面的编码x组合,此时可能有两种解码方式,与x组合成xy,或者不组合,而是单独表示为x,y。
- 当组合有可能发生时,比如x=1,y=3,此时
- 若组合成
xy,则 - 若单独表示为
y,则
- 当组合不可能发生时,比如x=2,y=9,
y只能单独表示一个字母,此时
由此我们可以得到如下代码。
参考答案
public class Solution {
public int numDecodings(String s) {
int n = s.length();
int[] dp = new int[n];
if (s.charAt(0) == '0') {
return 0;
}
dp[0] = 1;
for (int i = 1; i < n; i++) {
if (s.charAt(i) == '0') {
// only 10 and 20 are valid, and it doesn't increase the number of decoding ways
if (s.charAt(i - 1) == '1' || s.charAt(i - 1) == '2') {
dp[i] = i-2 >= 0 ? dp[i-2] : 1;
// 00 or 30... is invalid
} else {
return 0;
}
} else if (s.charAt(i - 1) == '1'
|| (s.charAt(i) <= '6' && s.charAt(i - 1) == '2')) {
// if 11= < xy <= 26 it can be decoded in 2 ways: x,y or xy
dp[i] = i-2 >= 0 ? dp[i-2] + dp[i-1] : 2;
} else {
// if xy < 10 or xy > 26 it can only be decoded in 1 way: x,y
dp[i] = dp[i-1];
}
}
return dp[n-1];
}
}
拓展训练
看看其他的动态规划问题吧!
[Leetcode][Hard] Remove Boxes 移除盒子 | Java
或者到作者的LeetCode专栏中看看,有没有其他感兴趣的问题吧!