給定一個數字,我們按照如下規則把它翻譯為字符串:0 翻譯成 “a” ,1 翻譯成 “b”,……,11 翻譯成 “l”,……,25 翻譯成 “z”。一個數字可能有多個翻譯。請編程實現一個函數,用來計算一個數字有多少種不同的翻譯方法。
示例 1:
輸入: 12258
輸出: 5
解釋: 12258有5種不同的翻譯,分別是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
思路
看到該題的第一個想法就是使用動態規劃求解,而動態規劃的核心就是寫出解題的方程
對于這個題目來說,因為數字只能一位一位的翻譯或者兩位一起翻譯
當我們將長度為n的數字最后一位單獨翻譯的時候,其解法與n-1的解法是相等的,即f(n)=f(n-1)
對于最后兩位一起翻譯,將后兩位視作一個整體的話,其解法與n-2相同,但是由于后兩位并不一定只能一起,所以還需要加上最后一位單獨翻譯的結果,即f(n)=f(n-1)+f(n-2)
而后兩位一起翻譯時是需要考慮這兩位對應的數字是否在0-25之間,
當倒數第二位為0的時候,01-09顯然不在,所以不能同時解析后兩位,當兩位表示的數字大于25時,也超出了翻譯的最大范圍,同樣不滿足條件,這時就只能將最后一位單獨翻譯
當最后兩位在10-25之間時,這時候則可以將后兩位一起翻譯或者單獨翻譯最后一位
最后得到的結果就是
if 10<=最后兩位<=25
f(n)=f(n-1)+f(n-2)
else
f(n)=f(n-1)
實現
public int translateNum(int num) {
String value = String.valueOf(num);
if (value.length() == 1) {
return 1;
}
int total = 1, a0, a1 = 1;
for (int i = 1; i < value.length(); i++) {
a0 = a1;
a1 = total;
char c1 = value.charAt(i - 1);
char c2 = value.charAt(i);
if (c1 == '1' || (c1 == '2' && c2 <= '5')) {
total += a0;
}
}
return total;
}
如果數字只有一位,那就只有一個解
total表示當前總的解,因為我們是從長度2開始遍歷,所以total的取值跟長度1時相同
a0和a1表示f(0)和f(1)的解,也就是DP的邊界值
每次循環的時候,n增加1,對應的a1變為f(n-2)的值,所以賦值給a0,total表示的到上次為止的所有解,即f(n-1)的值,所以賦值給a1
再判斷n和n-1的組合值是不是在10到25之間,是的話,total就需要加上f(n-2)的值,即a0,否則就等于f(n-1)的值,就是其本身