Question:
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.
方法:
和fibonacci的一类递归方法类似的算法。可以有递归和DP两种标志性解法。
递归:base case就是当string便利到只有一位或者长度为零的时候,返回1,注意‘0’的处理共有两种情况,一种是‘10’,‘20’,其他情况都返回0。
DP:看似很方便,但是用到了two pointers的解法,一个i指向string,另一个j指向dp[],同时右移。注意dp的array比string多出一位,并且虽然判断的几个基本情况和递归的方法一样,但是判断的方式有所变化,具体解法请看Code。
Code:
/DP: WHAT'S THE ARRAY'S USE?
public class Solution {
public int numDecodings(String s) {
// Start typing your Java solution below
// DO NOT write main() function
if(s.length()==0) return 0;
int[] dp = new int[s.length()+1];
dp[0] = 1;
for(int i=0, j=1; i<s.length(); i++, j++){
if(s.charAt(i) == '0'){
if(i>0 && (s.charAt(i-1)=='1' || s.charAt(i-1)=='2')) dp[j] = dp[j-2];
else return 0;
}
else if(i>0 && (s.charAt(i-1)=='1' || (s.charAt(i-1)=='2' && s.charAt(i)>='1' && s.charAt(i)<='6')))
dp[j] = dp[j-1] + dp[j-2];
else dp[j] = dp[j-1];
}
return dp[s.length()];
}
}
//RECURSION: BASE CASE + RECURSIVE
public class Solution {
public int numDecodings(String s) {
// Start typing your Java solution below
// DO NOT write main() function
if(s.length() == 0) return 0;
return recImp(s);
}
private int recImp(String s){
if(s.length()>0 && s.charAt(0)=='0') return 0;
if(s.length()==0 || s.length()==1) return 1;
char c1 = s.charAt(0), c2 = s.charAt(1);
if((c1=='1' || c1=='2') && c2=='0') return recImp(s.substring(2));
else if((c1=='1' && c2!='0') || (c1=='2' && c2>=1 && c2<='6'))
return recImp(s.substring(1)) + recImp(s.substring(2));
else return recImp(s.substring(1));
}
}
小结:
原本很想统一DP和RECURSIVE的判断的方法使其一致,但是最终还是没有想出来。如果各位看官想出来或者有什么意见,尽管留言。