劍指offer(7)
今天的幾道題目都是關於斐波那契數列的。
題目1:
大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。
n<=39
傳統的方法采用遞歸函數,這種方法也是我們在大學剛剛接觸遞歸函數時老師給的例子。但這種方法會消耗大量的時間和空間,所以在此我們不使用這種方法。
思路大致如下圖
public class Solution { public int Fibonacci(int n) { int[] a ={0,1}; if(n<2){ return a[n]; } int numberOne = 0; int numberTwo = 1; int numberResult = 0; for(int i=2; i<=n; i++){ numberResult = numberOne + numberTwo; numberOne = numberTwo; numberTwo = numberResult; } return numberResult; } }
題目2:一只青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。
先考慮簡單情況,如果只有一級臺階,那麽結果很顯然是1.如果有兩級臺階,那麽我們就有兩個選擇了,一種是一次跳一級,跳兩次,另外一種是一次跳兩級。
接著考慮一般情況,把n級臺階時的調發看做n的函數f(n),當n>2時,如果第一次跳一級那麽我們可以表示成1+f(n-1),若第二次跳兩級我們可以表示成2+f(n-2),第一種情況有f(n-1)種方案,第二種方案有f(n-2)種方案,這樣,總體我們就有f(n)=f(n-1)+f(n-2)種方案,不難發現這實際上就是斐波那契數列。
public class Solution { public int JumpFloor(int target) { int[] a ={0,1,2}; if(target<=2){ return a[target]; } int numberOne = 1; int numberTwo = 2; int numberResult = 0; for(int i=3; i<=target; i++){ numberResult = numberOne + numberTwo; numberOne = numberTwo; numberTwo = numberResult; } return numberResult; } }
題目3:一只青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
這道題目可以沿用上一題的思路,如果只有一級臺階,那麽只有一種法案,如果有兩級臺階我們就回到了上一題f(2)=f(2-1)+f(2-2),如果有三級臺階那麽我們可以第一次跳一級1+f(3-1),第一次跳兩級2+f(3-2),或者第一次跳三級3+f(3-3),可得出f(3)=f(3-1)+f(3-2)+f(3-3)。
當有n級臺階時,f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)+f(n-1)
當有n-1級臺階時,f(n-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)
不難發現f(n)=2*f(n-1),一個等比數列,易得f(n)=2^(n-1)
public class Solution { public int JumpFloorII(int target) { int jumpNumber = 1; while((--target)!=0){ jumpNumber*=2; } return jumpNumber; } }
題目4:
我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?
這題依舊是上面的思想,只是理解上有點小坑。
public class Solution { public int RectCover(int target) { int a[] = {0,1,2}; if(target<=2){ return a[target]; } int numberOne = 1; int numberTwo = 2; int numberResult = 0; for(int i=3;i<=target;i++){ numberResult = numberOne + numberTwo; numberOne = numberTwo; numberTwo = numberResult; } return numberResult; } }
劍指offer(7)