题目
思路: 动态规划
- 和剑指46的区别在于,这个题1对应A,单个的0是无效的。
- 转移方程:
dp[i] = dp[i - 1] + dp[i - 2]或者dp[i] = dp[i - 1];
代码
DP多一位,方便初始化
class Solution {
public int numDecodings(String s) {
// dp[i]: ways of decode s substring [0, i-1].
// this way helps recude custom checks for first two char
// if let dp[i]: ways of decode s substring [0, i], when starting with dp[2],
// we need to consider the first 3 digits, which is more complex
int[] dp = new int[s.length() + 1];
dp[0] = 1; // e.g. first two is 15, try dp[2] can explain we set dp[0]=1
if (s.charAt(0) == '0') {
dp[1] = 0;
} else {
dp[1] = 1;
}
for (int i = 2; i < s.length() + 1; i++) {
// if we can decode single digit at index i - 1
if (s.charAt(i - 1) != '0') {
dp[i] = dp[i - 1];
}
int num = Integer.valueOf(s.substring(i - 2, i));
if (num <= 26 && num >= 10) {
dp[i] += dp[i - 2];
}
}
return dp[s.length()];
}
}
o1空间优化
class Solution {
public int numDecodings(String s) {
// dp[i]: ways of decode s substring [0, i-1].
// this way helps recude custom checks for first two char
// if let dp[i]: ways of decode s substring [0, i], when starting with dp[2],
// we need to consider the first 3 digits, which is more complex
// int[] dp = new int[s.length() + 1];
// dp[0] = 1; // e.g. first two is 15, try dp[2] can explain we set dp[0]=1
int prev2 = 1;
// if (s.charAt(0) == '0') {
// prev = 0;
// } else {
// prev = 1;
// }
int prev = s.charAt(0) == '0'? 0 : 1;
for (int i = 2; i < s.length() + 1; i++) {
// if we can decode single digit at index i - 1
int cur = 0;
if (s.charAt(i - 1) != '0') {
// dp[i] = dp[i - 1];
cur = prev;
}
int num = Integer.valueOf(s.substring(i - 2, i));
if (num <= 26 && num >= 10) {
// dp[i] += dp[i - 2];
cur += prev2;
}
prev2 = prev;
prev = cur;
}
return prev;
}
}
dp 长= s,初始化麻烦
class Solution {
public int numDecodings(String s) {
int[] dp = new int[s.length()];
//特判,“05,0”这样的不行
if (s.charAt(0) == '0') {
return 0;
}
dp[0] = 1;
//长度为1
if (s.length() == 1) {
return dp[0];
}
// 长度为2
int tmp = Integer.parseInt(s.substring(0, 2));
if (s.charAt(1) == '0') {
if (s.charAt(0) == '1' || s.charAt(0) == '2') {//只允许10、20
dp[1] = 1;
} else {//30、40不行
return 0;
}
} else if (tmp >= 11 && tmp <= 26) {//上面已经排除了10、20的情况
dp[1] = 2;
} else {
dp[1] = 1;
}
for (int i = 2; i < s.length(); i++) {
int tmp1 = Integer.parseInt(s.substring(i - 1, i + 1));//当前位和前一位组成的字符串
if (s.charAt(i) == '0') {
if (s.charAt(i - 1) == '1' || s.charAt(i - 1) == '2') {//只允许10、20
dp[i] = dp[i - 2];
} else {//30、40不行
return 0;
}
} else if (tmp1 >= 11 && tmp1 <= 26) {
dp[i] = dp[i - 1] + dp[i - 2];
} else {
dp[i] = dp[i - 1];
}
}
return dp[s.length() - 1];
}
}