題目描述
一只青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
我的想法
因為和斐波那契變種的跳臺階很像,首先想到的還是寫遞歸公式,看能不能推出什么。表面上有種f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n - (n-1))的感覺,發現如果真的是這樣,完全可以化簡成f(n) = 2^(n-2) * f(1),但是這當然是錯的,細細一想就會發現會多出很多重復情況,這個式子完全不可取。
于是換一種思路,可以去選擇臺階,選擇跳上n階所踩過的臺階。于是得出這樣的式子,f(n) = 1 + C(1, n-1) + C(2, n-2) + ... + C(n-1, n-1),這很數學。列出階乘公式,帶入很容易就ac了。
代碼如下:
public class Solution {
public int JumpFloorII(int target) {
int rtn = 1;
long njie = jiecheng(target - 1);
for (int i = 1; i < target; i++) {
rtn += njie / (jiecheng(i) * jiecheng(target - 1 - i));
}
return rtn;
}
public long jiecheng(int start) {
long rtn = 1;
for (int i = start; i >= 1; i--) {
rtn *= i;
}
return rtn;
}
}
別人的思路
看到解析第一個,又驚了,只有幾行代碼......思路和我的很不一樣,具體是這樣的:
f(1) = f(1-1) = 1
f(2) = f(2-1) + f(2-2) = f(1) + f(0)
f(3) = f(3-1) + f(3-2) + f(3-3) = f(2) + f(1) + f(0)
f(n) = f(n-1) + f(n-2) + ... + f(n-n) = f(0) + f(1) + f(2) + ... + f(n-1)
解釋一下就是當跳的臺階只有一階時,只有一種跳法。
當跳兩階臺階時,可以分兩種方式,直接跳上去,另一種是先跳一階,再跳上去,只是第二種方法跳過第一步后就變成跳一階的情況。
了。
同樣跳三階樓梯,分三種,1.先跳一階后轉換成f(2),2.先跳兩階轉換成f(1),3.直接跳上去。
這種思路就推出了上面的公式。化簡一下:
f(n-1) = f(0) + f(1) + f(2) + ... + f(n-2)
f(n) = (f(0) + f(1) + f(2) + ... + f(n-2)) + f(n-1) = 2*f(n-1)
推出來的公式真的超簡單啊,代碼就沒有什么難度了
f(n) = 2*f(n-1)。
public class Solution {
public int JumpFloorII(int target) {
if (target <= 1) {
return 1;
} else {
return 2 * JumpFloorII(target - 1);
}
}
}
但是畢竟這是遞歸,來看幾個優化:
迭代:
class Solution {
public int JumpFloorII(int target) {
int rtn = 1;
while (--target != 0) {
rtn *= 2;
}
return rtn;
}
}
位運算一行代碼:
class Solution {
public int JumpFloorII(int target) {
return 1<<(target-1);
}
}
可怕可怕,移位代替了乘2的工作,運算速度更快。
感覺自己想到方法已經很不容易了,看到別人的算法,感覺思維好有差距,還是要多練多練。