5.19
这个题目真的写的我好憔悴啊。
刚开始的思路很正确,从后向前遍历字符串,
/* 当在原有的字符串的基础上重新加入一个新的数字时
首先要判断,加入这个数字后,新的字符串是不是合法
不合法有两层含义 :
1,出现“00”、“30”,“90”等,直接返回0就可以了
2,数字 只是单纯不在区间【1,26】之内。
当加入新的数字时,新的字符串的长度为n
如果数字是合法的 res[n] = res[n-1] + res[n-2]
如果数字是不合法的 res[n] = res[n-1]
*/
采用非递归的方式,表达式也是正确的,但是有一下几个细节在最初的时候并没有考虑到。
1.数据可能是不合法的,这样就没有对应的解码方式
1.1 字符串以0 开头
1.2 字符串中含有“00”、“30”等情况
2. 初始条件没有设置正确。
2.1 当最后两个字母为“10”、“11”、“31”、“01”大概这几种情况,需要认真考虑
3. 表达式还是欠考虑。
3.1 比如 加上一个字符后,字符串的变化情况为 "111" -> "0111",
3.2 在上述情况下,又加入字符,字符的变化情况为“0111”->"10111"
3.3 继续加入字符,字符串的变化情况为“10111”->"110111"
在这种情况下,就不可以单纯地采用 res_2 = res_1; res_1=res;进行状态的变化了,需要进行特殊处理。
大概就是这样。现在思路清晰了,但是代码是一点儿一点儿加上去的,写的很不好。但是懒得重新按照完整的逻辑再来一遍了。就这样吧。
被破题整的很崩溃。
public class Solution {
/**
* @param s a string, encoded message
* @return an integer, the number of ways decoding
*/
public int numDecodings(String s) {
// Write your code here
int length = s.length();
if(length == 0){
return 0;
}
if(s.startsWith("0")){
return 0;
}
if(length == 1){
return 1;
}
int flag = length - 2;
int res = 0;
if(s.charAt(length -1) != '0'){
res = 1;
}
// substring(i,j) 包括i,却不包括j
String tmp = s.substring(flag,length);
int isLegal = isLegal(tmp);
int res_1 = res;// 存储 n - 1 的值
int res_2 = 0;// 存储 n - 2 的值
/* 当在原有的字符串的基础上重新加入一个新的数字时
首先要判断,加入这个数字后,新的字符串是不是合法
不合法有两层含义 :
1,出现“00”、“30”,“90”等,直接返回0就可以了
2,数字 只是单纯不在区间【1,26】之内。
当加入新的数字时,新的字符串的长度为n
如果数字是合法的 res[n] = res[n-1] + res[n-2]
如果数字是不合法的 res[n] = res[n-1]
*/
if(isLegal == 0){
return 0;
}
if(isLegal == 1){
res_2 = res_1;
res_1 = res;
res = res_1 + 1;
}
else{
res_2 = res_1;
res_1 = res;
res = res_1;
}
while(flag > 0){
flag --;
tmp = s.substring(flag,length);
isLegal = isLegal(tmp);
if(isLegal == 0){
return 0;
}
if(tmp.startsWith("0")){
res_1 = 0;
res_2 = res;
continue;
}
if(tmp.charAt(2) == '0'){
res_2 = 0;
res_1 = res;
continue;
}
//System.out.println("tmp:" + tmp + ";flag:" + (length - flag));
//System.out.println("前:res:" + res +"; res1:" + res_1 + "; res2:" + res_2);
if(isLegal == 1){
res_2 = res_1;
res_1 = res;
res = res_1 + res_2;
//System.out.println("数据合法");
}
else{
res_2 = res_1;
res_1 = res;
res = res_1;
}
//System.out.println("后:res:" + res +"; res1:" + res_1 + "; res2:" + res_2);
}
return res;
}
// 要考虑00,30,40 这种无解码方式的情况
public int isLegal(String s){
// 1 代表合法 -1 代表超过26的情况,0 代表出现了00,30,40这种情况,
int length = s.length();
if(length <= 1){
return -1;
}
int x = s.charAt(0) - '0';
int y = s.charAt(1) - '0';
//System.out.println("X:" + x + ";Y:" + y);
if( y == 0 && x >= 3){
return 0;
}
if( y == 0 && x == 0){
return 0;
}
if(x == 0){
return -1;
}
if(10*x + y <= 26){
return 1;
}
return -1;
}
}