劍指Offer面試題9(java版) 斐波那契數列

2021-07-23 10:40:07 字數 2997 閱讀 9397

題目一:寫乙個函式,輸入n,求斐波那契數列的第n項。斐波那契數列的定義如下:

1、效率很低效的解法,挑剔的面試官不會喜歡

很多c語言的教科書在講述遞迴函式的時候,都戶拿fibonacci作為例子,因此很多的應聘者對這道題的遞迴解法都很熟悉。

下面是實現**

我們教科書上反覆用這個問題來講解遞迴的函式,並不能說明遞迴的解法最適合這道題目。面試官會提示我們上述遞迴的解法有很嚴重的效率問題要求我們分析原因。

我們以求解f(10)為例來分析遞迴的求解過程。想求得f(10),需要先求出f(9)和f(8).同樣求f(9),需要先求得f(8)和f(7)。我們用樹來構造這種依賴關係。如圖所示:

我們不難發現在這顆樹中有很多的節點是重複的,而且重複的節點數會隨著n的增大而急劇增加,這意味著計算量會隨著n的增大而急劇增大。事實上,用遞迴的方法計算的時間複雜度是以n的指數的方式遞增的。讀者不妨求fibonacci的第100項試試,感受一下這樣的遞迴會慢到什麼程度。

2、面試官期待的適用解法:

其實改進的方法比並不複雜。上述的遞迴**之所以慢是因為重複的計算太多,我們只要想避免重複計算就型了。比如我們可以把已經得到的數列中間項儲存起來,如果下次需要計算的時候我們先查詢一下,如果前面已經計算過就不用重複計算了。

更簡單的方法是從下往上計算,首先計算f(0)和f(1)算出f(2),再根據f(1)和f(2)算出f(3)……依次類推就可以算出第n項了。很容易理解,這種思路的時間複雜度為o(n)。實現**如下:

[html]view plain

copy

/**  

* 寫乙個函式,輸入n,求斐波那契(fibonacci)數列的第n項。  

*/  

package swordforoffer;  

/**  

* @author jinshuangqi  

*  * 2023年7月29日  

*/  

public class e09fibonacci   

if(n

== 1)  

for(int i= 2

;i<

= n ;i++)  

return result;  

}  public static void main(string args)  

}  

3、時間複雜度o(logn)但不夠使用的解法)

通常面試到這裡就差不多了,儘管我們還有比這更快的o(logn)解法,由於這種演算法需要用到乙個很生僻的數學公式,因此很少有面試官會要求我們掌握。不過以防萬一,我們還是介紹一下這種演算法。

我們先來聊i額乙個數學公示:

解法比較:

用不同的方法求斐波那契數列的時間效率大不相同。第一種基於遞迴的解法雖然直觀但時間效率太低,實際軟體開發中不會使用這種方法,也不可能得到面試官的青睞。第二種方法把遞迴的演算法用迴圈來實現,極大的提高了時間效率。第三種方法把求斐波那契數列轉換成求矩陣的乘方,是一種很有創意的演算法。雖然我們可以喲個o(logn)求的矩陣的n次方,但由於隱含的時間常熟較大,很少會有軟體採用這種演算法,另外,實現這種演算法的**也交複雜,不太適用於面試。

相關題目:

我們可以用2*1的小矩形橫著或豎著去覆蓋更大的矩形。請問用8個2*1的小矩形無重疊地覆蓋乙個2*8的大矩形,總共有多少方法?

我們先把2*8 的覆蓋方法記為f(8)。用第乙個1*2小矩形去覆蓋大矩形的最左邊時有兩個選擇,豎著放或者橫著放。當豎著放的時候,右邊還剩下2*7的區域,這種情形下的覆蓋方法記為f(7).接下來考慮橫著放的情況。1*2的小矩形橫著放在左上角的時候,左上角必須和橫著放乙個1*2的小矩形,而在右邊還剩下2*6的區域,這種情形下的覆蓋方法即為f(6),因此f(8)=f(7)+f(6).此時,我們可以看出,這仍然是斐波那契數列。

擴充套件部分:

乙隻青蛙一次可以跳上1級台階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上乙個n級的台階總共有多少種跳法。

用fib(n)表示青蛙跳上n階台階的跳法數,青蛙一次性跳上n階台階的跳法數,是定fib(0)=1;

當n = 1時,只有一種跳法,即1階跳:fib(1) =  1;

當n = 2時,有兩種跳法,一階跳和二階跳:fib(2) = fib(1)+fib(0) = 2;

當n  =3時,有三種跳法,第一次跳出一階後,後面還有fib(3-1)中跳法;第一次跳出二階後,後面還有fib(3-2)中跳法;第一次跳出三階後,後面還有fib(3-3)中跳法

fib(3)= fib(2)+fib(1)+fib(0) = 4

當n= n時,共有n種跳法方式,第一次跳出一階後,後面還有fib(n-1)種跳法;第一次跳出二階後,後面還有fib(n-2)種跳法,第一次跳出n階後,後面還有fib(n-n)種體哦啊發。

fib(n) = fib(n-1)+fib(n-2)+fib(n-3)+..........+fib(n-n)=fib(0)+fib(1)+fib(2)+.......+fib(n-1)

又因為fib(n-1)=fib(0)+fib(1)+fib(2)+.......+fib(n-2)

兩式相減得:fib(n)-fib(n-1)=fib(n-1)         *****》  fib(n) = 2*fib(n-1)     n >= 2

遞迴等式如下:

劍指offer第二版 面試題9(java)

面試題9 用兩個棧實現佇列 題目描述 方法 兩個棧 stack1 stack2 插入時,直接放入stack1 刪除時,直接彈出pop2中的物件 如果pop2為空,則先將pop1中的物件放入stack2中,再從stack2裡pop第乙個 如 依次放入stack1中1 2 3,在彈出並放入stack2中...

劍指offer 面試題9

對於第二道題目,我們可以認為有乙個函式f 放台階數是n時,有f n 種跳法,當台階數n 1時有f n 1 種跳法,以此類推 那麼f n 等於多少呢?青蛙第一次跳有兩種可能,要麼跳乙個台階,要麼跳兩個台階。跳乙個台階後還剩下n 1個台階,n 1個台階跳法有f n 1 種。跳兩個台階後還剩下n 2個台階...

劍指offer 面試題9

面試題 9 斐波那契數列 題目一 寫入乙個函式,輸入 n,求斐波那契切數列的第 n項。題目二 乙隻青蛙一次可以跳上一級台階,也可以跳上兩級台階,求該青蛙一次跳上乙個 n級的台階總共有多少種跳法。首先我們來看第二題,我們可以假設有乙個台階,青蛙跳法 1種 有兩個台階,青蛙跳法 2種 有三個台階,青蛙跳...