日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

剑指 Offer 10- I. 斐波那契数列 (从重叠子问题到备忘录到dp数组迭代解法)

發(fā)布時(shí)間:2023/12/1 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 剑指 Offer 10- I. 斐波那契数列 (从重叠子问题到备忘录到dp数组迭代解法) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 題目描述
  • 1、暴力遞歸法的重疊子問(wèn)題
  • 2、備忘錄解法
  • 3、dp數(shù)組迭代算法
  • 4、滾動(dòng)數(shù)組優(yōu)化
  • 5、參考鏈接

題目描述

寫(xiě)一個(gè)函數(shù),輸入 n ,求斐波那契(Fibonacci)數(shù)列的第 n 項(xiàng)。斐波那契數(shù)列的定義如下:

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契數(shù)列由 0 和 1 開(kāi)始,之后的斐波那契數(shù)就是由之前的兩數(shù)相加而得出。

答案需要取模 1e9+7(1000000007),如計(jì)算初始結(jié)果為:1000000008,請(qǐng)返回 1。

1、暴力遞歸法的重疊子問(wèn)題

暴力遞歸法最為常見(jiàn),但是同時(shí)它的時(shí)間復(fù)雜度也是最高的,附帶了許多重復(fù)計(jì)算。

class Solution { public:int fib(int n) {if(n==0) return 0;else if(n == 1 || n == 2) return 1;else return (fib(n - 1) + fib(n - 2))%1000000007;} };

畫(huà)出遞歸樹(shù):

算法時(shí)間復(fù)雜度為遞歸二叉樹(shù)結(jié)點(diǎn)總數(shù),為O(2^n)。f(18)、f(17)被重復(fù)計(jì)算了,并且以f(18)為根節(jié)點(diǎn)的遞歸樹(shù)體積也是十分巨大的,如果再算一遍會(huì)耗費(fèi)大量的時(shí)間。
這個(gè)問(wèn)題性質(zhì)我們可以描述為“重疊子問(wèn)題”。

2、備忘錄解法

既然是重復(fù)計(jì)算的問(wèn)題,我們就可以構(gòu)造一個(gè)備忘錄。
每次計(jì)算出某個(gè)子問(wèn)題的答案先別著急返回,先記到備忘錄中再返回;
每次遇到一個(gè)子問(wèn)題,先去備忘錄中查找,如果已經(jīng)解決了這個(gè)問(wèn)題,就直接把答案拿過(guò)來(lái)用,不再進(jìn)行計(jì)算。

class Solution { public:int search_helperTab(vector<int >& helperTab,int n){//n較小的直接返回if(n == 1 || n == 2) return 1;//如果已經(jīng)計(jì)算過(guò)了,直接返回計(jì)算過(guò)的值if(helperTab[n] != 0) return helperTab[n];//如果沒(méi)有計(jì)算過(guò),則需要重新計(jì)算一遍else{helperTab[n] = (search_helperTab(helperTab,n-1) + search_helperTab(helperTab,n-2))%1000000007;}return helperTab[n];}int fib(int n) {if(n==0) return 0;//構(gòu)建一個(gè)備忘錄vector<int >helperTab(n+1,0);return search_helperTab(helperTab,n);} };

帶備忘錄的遞歸算法,將一顆存在巨量冗余的遞歸樹(shù)剪枝為沒(méi)有冗余的遞歸圖。
遞歸算法時(shí)間復(fù)雜度=子問(wèn)題個(gè)數(shù) * 解決子問(wèn)題所需要的時(shí)間。
由于不存在冗余計(jì)算,所以子問(wèn)題個(gè)數(shù)為O(n);解決一個(gè)子問(wèn)題的時(shí)間是O(1);
所以本算法的時(shí)間復(fù)雜度是O(n)。
注意,我們剛剛畫(huà)的遞歸樹(shù)是從上向下延伸的,都是從一個(gè)規(guī)模較大的原問(wèn)題,向下逐漸分解規(guī)模,直到觸底(f(1)、f(2)),然后逐層返回答案,這就是自頂向下。

如果直接從最底下的最小規(guī)模的f(1)、f(2)開(kāi)始往上推導(dǎo),直到f(20),這就是動(dòng)態(tài)規(guī)劃的思路。

3、dp數(shù)組迭代算法

class Solution { public:int fib(int n) {if(n==0) return 0;if(n == 1 || n == 2) return 1;//構(gòu)建一個(gè)備忘錄vector<int >dp(n+1,0);dp[1]=dp[2]=1;for(int i = 3;i <= n;i++)dp[i]=(dp[i-1]+dp[i-2])%1000000007;return dp[n];} };

4、滾動(dòng)數(shù)組優(yōu)化

狀態(tài)方程中的當(dāng)前狀態(tài)只由前兩個(gè)狀態(tài)決定,所以不需要一個(gè)數(shù)組進(jìn)行存放。

class Solution { public:int fib(int n) {if(n==0) return 0;if(n == 1 || n == 2) return 1;int pre=1,curr=1;for(int i = 3;i <= n;i++){int sum=(pre+curr)%1000000007;pre=curr;curr=sum;}return curr;} };

這樣空間復(fù)雜度就降到O(1)了。

5、參考鏈接

劍指 Offer 10- I. 斐波那契數(shù)列
labuladong:動(dòng)態(tài)規(guī)劃詳解(修訂版)

總結(jié)

以上是生活随笔為你收集整理的剑指 Offer 10- I. 斐波那契数列 (从重叠子问题到备忘录到dp数组迭代解法)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。