題目
給定一個數字,我們按照如下規則把它翻譯爲字符串:0 翻譯成 “a” ,1 翻譯成 “b”,……,11 翻譯成 “l”,……,25 翻譯成 “z”。一個數字可能有多個翻譯。請編程實現一個函數,用來計算一個數字有多少種不同的翻譯方法。
示例 1:
輸入: 12258
輸出: 5
解釋: 12258有5種不同的翻譯,分別是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:
0 <= num < 2^31
解題思路
定義遞歸函數f(i)表示從第i位數字開始的不同翻譯的數目,那麼
f(i)=f(i+1)+g(i,i+1)*f(i+2),其中當第i位數字和第i+1位數字拼接起來的兩位數在[10,25]範圍內時,g(i,i+1)=1,否則g(i,i+1)=0。
但自上向下的遞歸做法求解時會存在重複的子問題,於是我們可以採取自下而上的做法,先求解最小的子問題,從而消除遞歸時重複的子問題。
定義一個長度爲n的dp數組,dp[i]表示第i個數字開始的不同翻譯數目,我們最終要求的是dp[0],所以我們從後往前遍歷,初始時先令dp[n-1]=1。
1)當i=n-2時,若第i,i+1兩位數拼接起來的兩位數在[10,25]範圍內時,dp[i]=dp[i+1]+1;否則,dp[i]=dp[i+1]。
2)當0<=i<n-2時,若第i,i+1兩位數拼接起來的兩位數在[10,25]範圍內時,dp[i]=dp[i+1]+dp[i+2];否則,dp[i]=dp[i+1]。
3)最後返回dp[0]即可。
代碼
class Solution {
public int translateNum(int num) {
String s = String.valueOf(num);
char[] nums = s.toCharArray();
int n = nums.length;
int[] dp = new int[n];
dp[n-1] = 1;
for(int i=n-2; i>=0; i--){
int index1 = nums[i]-'0';
int index2 = nums[i+1] - '0';
int digit = index1*10 + index2;
if(10<=digit && digit<=25){
if(i==n-2){
dp[i]=dp[i+1]+1;
}else{
dp[i]=dp[i+1]+dp[i+2];
}
}else{
dp[i]=dp[i+1];
}
}
return dp[0];
}
}