題目:給定一個數字,我們按照如下規則把它翻譯爲字符串:0翻譯成“a”,1翻譯成“b”,……,11翻譯成“l”,……,25翻譯成“z”。一個數字可能有多個翻譯。例如,12258有5種不同的翻譯,分別是“bccfi”、“bwfi”、“bczi”、“mcfi”和“mzi”。請編程實現一個函數,用來計算一個數字有多少種不同的翻譯方法。
思路:到最後感覺就是一道找規律的題目。使用動態規劃解題。。。
先看一張圖:
使用上述遞歸方式的話,會有很多重複的子運算,入兩邊都會子弟規258這個數字。
那麼正題就來了,使用動態規劃優化下就歐了。
我們通過找規律發現:f(i) = f(i+1)+g(1+1,i+2)*f(i+2),代表從當前位置開始至最後一位,存在幾種組合,g(i+!,i+2)代表第i+1與i+2個數拼接到一起是不是在10~25這個範圍內。先別蒙我舉個例子解釋下就感覺很簡單了。
就拿題中給的數來說12258:這裏的i代表索引值index
f(4) = 1種 8->i
f(3) = 1種 58->fi
f(2) = 2種 258->cfi/zi
f(1) = 3種 2258->wfi/ccfi/czi
f(0) = 5種 12258->mzi/bwfi/bccfi/mcfi/bczi
好了,從上邊找到的規律就是f(i) = f(i+1)+g(1+1,i+2)*f(i+2)了
public int getNemberCount(int number){
if(number<0) return 0;
String numberS = String.valueOf(number);
int length = numberS.length();
int [] counts= new int[length];
for (int i=length-1;i>=0;i--){
if(i==length-1) {
counts[i] = 1;
}else {
counts[i] =counts[i+1];
if(isInTheRange(i,numberS)) { // 判斷是否在範圍內10~25
if(i+2==length) { // 這種條件下最右兩位爲兩種情況,所以單獨處理
counts[i]+=1;
}else {
counts[i]+=counts[i+2];
}
}
}
}
return counts[0];
}
private boolean isInTheRange(int i, String num) {
String numberS = num.substring(i, i+2);
Integer number = Integer.valueOf(numberS);
return number >= 10 && number <= 25;
}
- 時間複雜度:O(n)。
- 空間複雜度:O(n)。