Problem: 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 an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).
The number of ways decoding "12"
is 2.
分析:
这道题和Restore IP Address很像,dfs的思路可以参考那一题,同时如果输入数据过大的话,我们也可以用DP来解决
Solution1: (dfs version) -- OJ大数据超时
public class Solution {
int num;
public int numDecodings(String s) {
if (s.length()==0) return 0;
num = 0;
dfs(s);
return num;
}
public void dfs(String s){
if (s.length()==0) num++;
for(int i=0;i<=1&&i<s.length();i++){
if (isValid(s.substring(0,i+1)))
dfs(s.substring(i+1));
}
}
public boolean isValid(String s){
if (s.charAt(0)=='0') return false;
int code = Integer.parseInt(s);
return code>=1 && code<=26;
}
}
需要注意的地方,
1. 每次dfs里面我们先从1位开始取,然后再取2位,要小心越界的问题,到后面字符的长度可能只有1位,所以i < s.length()
2. 检查字符是否Valid的时候和Restore IP Address一样,要小心0的情况,不过这道题比那道题简单,如果出现0直接返回False
来说一下DP的解法
从头到尾扫这个String,比如我们想知道到,从第一位到dp[i]这一位组成的String,有多少种解码组合,那么有两种情况
第一:如果dp[i]所对应的的单个字符可以解码,那么dp[i]就包括前dp[i-1]位所积累的组合数 dp[i] = dp[i-1]
第二:如果不仅dp[i]所对应的的单个字符可以解码,dp[i-1] - dp[i],两个字符组成的也可以解码,那么不仅包括dp[i-1]积累的组合数,也包括dp[i-2]位积累的组合数 dp[i] = dp[i-1] + dp[i-2]
我们建一个n+1的数组,为了程序简洁,我们在最前面放一个1。这样一来要注意数组里的index -1==String里的index
public class Solution {
public int numDecodings(String s) {
int n = s.length();
if (n==0) return 0;
int[] dp = new int[n+1];
dp[0] = 1;
if (isValid(s.substring(0,1))) dp[1] = 1;
else dp[1] = 0;
for(int i=2; i<=n;i++){
if (isValid(s.substring(i-1,i)))
dp[i] = dp[i-1];
if (isValid(s.substring(i-2,i)))
dp[i] += dp[i-2];
}
return dp[n];
}
public boolean isValid(String s){
if (s.charAt(0)=='0') return false;
int code = Integer.parseInt(s);
return code>=1 && code<=26;
}
}