package com.interview.algorithms.string;
/**
* Created_By: stefanie
* Date: 14-11-9
* Time: 下午8:45
*/
public class C11_36_DecodeWays {
public static int numDecodings(String s) {
if (s.length() == 0) return 0;
int[] sols = new int[s.length()]; //to avoid duplicated calculation
return numDecodings(s, 0, sols);
}
private static int numDecodings(String s, int offset, int[] sols) {
if (offset == s.length()) return 1; //reach the end of str, have decode all the chars,
if (offset == s.length() - 1) return (s.charAt(offset) == '0') ? 0 : 1; //have only one char
//have more than one char, recursively calling
if (sols[offset] != 0) return sols[offset];
char cur = s.charAt(offset);
char next = s.charAt(offset + 1);
if (cur == '0') return 0; //invalid case
else if (next == '0') { // 10... or 40...
if (cur != '1' && cur != '2') return 0; //invalid case, such 40
else sols[offset] = numDecodings(s, offset + 2, sols); //valid case, 10 or 20, can only move 2 steps
} else if (cur > '2' || cur == '2' && next > '6') { // > 26, can't be together with next, can only move 1 steps
sols[offset] = numDecodings(s, offset + 1, sols);
} else { // < 26, move 1 or 2 steps
sols[offset] = numDecodings(s, offset + 1, sols) + numDecodings(s, offset + 2, sols);
}
return sols[offset];
}
public static int numDecodingsDP(String s){
if(s.length() == 0 || s.charAt(0) == '0') return 0; //invalid
int[] sols = new int[s.length() + 1];
sols[0] = 1; //empty
sols[1] = 1;
for(int i = 2; i <= s.length(); i++){
int cur = s.charAt(i - 1) - '0';
int pre = s.charAt(i - 2) - '0';
if(cur == 0){
if(pre == 0 || pre > 2) return 0; //30, invalid
else sols[i] = sols[i - 2];
} else {
cur = pre * 10 + cur;
if(cur > 26 || cur < 10) sols[i] = sols[i - 1]; // <10 -> pre == 0
else sols[i] = sols[i - 1] + sols[i - 2];
}
}
return sols[s.length()];
}
public static int numDecodingsDPConstantSpace(String s){
if(s.length() == 0 || s.charAt(0) == '0') return 0; //invalid
int[] sols = new int[3];
sols[0] = 1; //empty
sols[1] = 1; //one char
for(int i = 2; i <= s.length(); i++){ //loop on 2nd char to end
int cur = s.charAt(i - 1) - '0';
int pre = s.charAt(i - 2) - '0';
if(cur == 0){
if(pre == 0 || pre > 2) return 0; //30, invalid
else sols[i%3] = sols[(i - 2)%3]; //10 or 20, sols[i] == sols[i-2];
} else {
cur = pre * 10 + cur; //calculate the num
if(cur > 26 || cur < 10) sols[i%3] = sols[(i - 1)%3]; // cur<10 -> pre == 0 or num > 26, can be together with prev, sols[i] == sols[i-1]
else sols[i%3] = sols[(i - 1)%3] + sols[(i - 2)%3]; //sols[i] == sols[i-1] + sols[i-2]
}
}
return sols[s.length()%3];
}
}