说在开头
要坚持刷题呀,坚持表达解题的思路,记录为了减少程序复杂度的每一点努力。
“说不定我一生涓滴意念,侥幸汇成河。”
读题
leetcode: 面试题46. 把数字翻译成字符串
描述:
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
测试用例:
输入: 12258
输出: 5
提示:
0 <= num < 231
看到这道题,想起了之前做过的一道动态规划题:新21点 这题当初把我折腾得一点想法都没有。
用12258和12222进行举例分析,发现结果很像斐波那契数列。
1:b
2:bc,m
2:bcc,bw,mc
5:bccf,bcz,bwf,mcf,mz
8:bccfi,bczi,bwfi,mcfi,mzi
1:b
2:bc,m
2:bcc,bw,mc
2:bccc,bcw,bwc,mcc,mw
2:bcccc,bcwc,bwcc,bww,mccc,mcw,mwc
从前往后的两种排法:
1:直接新增字符(当前翻译方法个数不变)
2:将新增的字符与原有的字符组合成新的字符(当前翻译方法个数增加)
推断:新增字符若满足条件,可以在下一次排结果时导致第二种排法
思路
1:当上一个字符为2且当前字符<=5 或者上一个字符为1时,满足第二个排法。
2:当不满足思路1时,满足第一个排法
实现
public int translateNum(int num) {
char[] numStr = String.valueOf(num).toCharArray();
int[] temp = new int[numStr.length];
temp[0] = 1;
int str1, str2;
for (int i = 1; i < numStr.length; i++) {
//上一个数字
str1 = numStr[i-1] - '0';
//当前数字
str2 = numStr[i] - '0';
if ((str1 == 2 && str2 <= 5) || str1 == 1) {
//可组成新的字符
if (i == 1) {
temp[1] = 2;
} else {
temp[i] = temp[i - 1] + temp[i - 2];
}
} else {
//不可组成新的字符
temp[i] = temp[i - 1];
}
}
return temp[numStr.length - 1];
}
自测
提交
嘿嘿,美滋滋~
标答
class Solution {
public int translateNum(int num) {
//先获取num的个位
int a = 1, b = 1, x, y = num % 10;
//遍历num的每一位
while(num != 0) {
// 丢弃num的个位
num /= 10;
//获取新的个位,也就是原本的十位
x = num % 10;
//求得两位数组成的结果
int tmp = 10 * x + y;
//在可组合的区间内,则翻译方法个数增加,否则翻译方法个数不变
int c = (tmp >= 10 && tmp <= 25) ? a + b : a;
//依次赋值,期待下一次循环
b = a;
a = c;
y = x;
}
return a;
}
}
想到此方法的前提:
1:此题字符串的正推和反推对最终的结果是一样的。
2:得到翻译方法个数增加的规律。
嘶~,标答思路恐怖如斯!!!