把数字翻译成字符串
问题描述
有一种将字母编码成数字的方式:‘a’->1, ‘b->2’, … , ‘z->26’。
现在给一串数字,返回有多少种可能的译码结果
示例1
输入:“12”
返回值:2
说明:2种可能的译码结果(”ab” 或”l”)
示例2
输入:“31717126241541717”
返回值:192
说明:192种可能的译码结果
解题思路
首先思考如何去编码。
-
只有1-26可以进行编码,所以只考虑单个字符编码,或者两个字符合并编码,这就将问题转换成跳台阶问题(每次可以上一个或者两个台阶)。
-
但是编码的数值范围是有要求的,只能匹配1-26,对其他数值要进行特殊处理
- 针对0
<1> 0在首位出现,只有0种译码结果
eg:0×,01×,011×
<2> 0在其他位置,只能去考虑它所在的前一位和0组合后再进行匹配,而两位中含有0的数值只有10,20。
故此,0的前一位只能是1或2且视为一种译码结果;其他均为0种译码结果
eg:30×,40×,100×,1030×,10√,20√,1020√- 针对大于26的数值
<1> 只能将其当单个字符处理 36->3和6
<2> 所以按照3去找最长字串时,遇到大于26时,需要停止查找并进行分割。1236->123和6 -
划分字符串,找字串满足可以单个匹配,也可两个匹配,它的编译结果就转成对应长度的跳台阶结果。从当前位置(第i位)往后寻找满足(第i位和第i+1位对应的数字小于等于26)条件的字长字串。
过程求解
长度为n的符合条件的字串的译码种类数
public int getTotal(int num) {
if (num == 1)
return 1;
if (num == 2)
return 2;
return getTotal(num - 1) + getTotal(num - 2);
}
对字符串进行分段处理
public int solve (String nums) {
if (nums.length() <= 2) {//对长度小于等于2的字符串进行处理
int n1 = Integer.parseInt(nums);
if (n1 == 0)
return 0;
if (n1 % 10 == 0 && n1 / 10 > 2)
return 0;
else if (n1 <= 10 || n1 > 26 || n1 == 20)
return 1;
else
return 2;
}
int m = 1;
for (int i = 0; i < nums.length(); i++) {
int begin = i;
if (nums.charAt(i) == '0') {
if (i - 1 < 0)//是否是以0为首位
return 0;
int u = nums.charAt(i - 1) - 48;
if (u == 0 || u > 2)//上一位是否符合条件
return 0;
} else if (i + 1 < nums.length() && nums.charAt(i + 1) == '0') {//i+1位为0
int u = nums.charAt(i) - 48;
if (u == 0 || u > 2)//当前位是否符合条件
return 0;
i++;
} else {
//找满足条件的最长子串
while (i < nums.length() - 1 &&
Integer.parseInt(nums.substring(i, i + 2)) <= 26) {
if (i + 2 < nums.length() && nums.charAt(i + 2) == '0')//判断是否结束寻找
break;
i++;
}
m *= getTotal(i - begin + 1);
}
}
return m;
}
当然代码中还有可优化的地方,也可能存在一些问题,欢迎指正。