斐波那契數與二分法的遞迴與非遞迴演算法及其複雜度分析

2022-05-23 03:21:20 字數 4162 閱讀 4367

在這個斐波那契數列中的數字,就被稱為斐波那契數。這個級數與大自然植物的關係極為密切。幾乎所有花朵的花瓣數都來自這個級數中的一項數字:菠蘿表皮方塊形鱗苞形成兩組旋向相反的螺線,它們的條數必須是這個級數中緊鄰的兩個數字(如左旋8行,右旋13行);還有向日葵花盤……直到最近的2023年,人們才對這個古老而重要的級數給出真正滿意的解釋:此級數中任何相鄰的兩個數,次第相除,其比率都最為接近0.618034……這個值,它的極限就是所謂的"**分割數"。

求第n個斐波那契數比較簡單可以直接套用公式n = 0,1 時,fib(n) = 1;n > =2 時,fib(n) = fib(n-2) + fib(n-1)在計算時有兩種演算法:遞迴和非遞迴。如下:

1

//非遞迴演算法

2long

long

fib1(size_t n)

7else13}

14return

c;15}16

intmain()

17 //此演算法最大的優點是不存在重複計算,故效率比遞迴演算法快的多得多。

1

//遞迴演算法

2long

long

fib2(size_t n)

7int

main()

8

遞迴可以使程式看起來比較簡潔,但缺點是效率比較低,並且可能導致棧溢位,當需要計算的數稍大一點,就需要很長的計算時間,因此需要靈活使用遞迴。

3.1 二分查詢的非遞迴演算法

1 template2 t* binarysearch(t* array,int number,const t&data)  //data要查詢的數,number查詢範圍長度,array要查詢的陣列3  

14else

if (array[mid]

15

18else

19

22}

23return

null;

24 }

3.2 二分查詢遞迴演算法

1 template2 t* binarysearch(t* left,t* right,const t&data)  3  

14else

15

18 }

時間複雜度:一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式f(n),進而分析f(n)隨n的變化情況並確定t(n)的數量級。這裡用"o"來表示數量級,給出演算法的時間複雜度。

t(n)=o(f(n));                 

它表示隨著問題規模的n的增大,演算法的執行時間的增長率和f(n)的增長率相同,這稱作演算法的漸進時間複雜度,簡稱時間複雜度。而我們一般討論的是最壞時間複雜度,這樣做的原因是:最壞情況下的時間複雜度是演算法在任何輸入例項上執行時間的上界,分析最壞的情況以估算演算法指向時間的乙個上界。

時間複雜度的分析方法:

(1)時間複雜度就是函式中基本操作所執行的次數;

(2)一般預設的是最壞時間複雜度,即分析最壞情況下所能執行的次數;

(3)忽略掉常數項;

(4)關注執行時間的增長趨勢,關注函式式中增長最快的表示式,忽略係數;

(5)計算時間複雜度是估算隨著n的增長函式執行次數的增長趨勢;

(6)遞迴演算法的時間複雜度為:遞迴總次數 * 每次遞迴中基本操作所執行的次數;

常用的時間複雜度有以下七種,演算法時間複雜度依次增加:o(1)常數型、o(log2 n)對數型、o(n)線性型、o(nlog2n)二維型、o(n^2)平方型、o(n^3)立方型、o(2^n)指數型。

空間複雜度:

演算法的空間複雜度並不是計算實際占用的空間,而是計算整個演算法的輔助空間單元的個數,與問題的規模沒有關係。演算法的空間複雜度s(n)定義為該演算法所耗費空間的數量級。

s(n)=o(f(n))  若演算法執行時所需要的輔助空間相對於輸入資料量n而言是乙個常數,則稱這個演算法的輔助空間為o(1); 

遞迴演算法的空間複雜度:遞迴深度n*每次遞迴所要的輔助空間, 如果每次遞迴所需的輔助空間是常數,則遞迴的空間複雜度是 o(n)。

5.1 非遞迴演算法時間複雜度分析

使用非遞迴演算法求到第n個斐波那契數,是從第2個數開始,將前兩個數相加求求後乙個數,再將後乙個數賦值給前乙個數,再計算前兩個數相加的結果。依次類推直到第n個數,用n-1個數和n-2個數相加求出結果,這樣的好處是,我們只計算了n-1次就求出了結果,即時間複雜度為o(n);我們以**中測試數10為例詳解求第十個數的過程。當n=10時,進入函式首先判斷,然後走下面的分支開始計算

計算了n-1次,得出了結果所以時間複雜度是o(n)。

非遞迴演算法空間複雜度分析

此函式內部最多時一共開闢了a, b, c, i四個變數空間複雜度是常數,即為o(1)。

5.2 遞迴演算法時間複雜度分析

在遞迴演算法中,求解fib2(n),把它推到求解fib2(n-1)和fib2(n-2)。也就是說,為計算fib2(n),必須先計算

fib2(n-1)和fib2(n-2),而計算fib2(n-1)和fib2(n-2),時按照表示式及計算法則,需先計算又必須先計算fib2(n-1),而fib2(n-1)由fib2(n-2)和fib2(n-3)計算得來,而這之中的和fib2(n-2)由fib2(n-3)和fib2(n-4)計算得來......依次類推,表面上看不出有何複雜度,但是仔細分析可知,每乙個計算fib2(n)的分支都會衍生出計算直至(1)和fib(0),也就是說每個分支都要自己計算數本身到1的斐波那契數列,這樣就增加了龐大且冗雜的運算量,還是以10 為例詳細計算說明

圖中數字代表第n個斐波那契數,圖中沒有全部將計算步驟畫出來,但是已經足夠說明問題,它的每一步計算都被分成計算前兩個斐波那契數,以此類推。那麼這就形成了一顆二叉樹,雖然不是滿二叉樹,但是我們分析的是最壞時間複雜度,而且只要估算出來遞迴次數隨n增長的趨勢即可,故可以近似將它看成滿二叉樹,其中的節點數就是計算的次數,也就是複雜度,由公式:節點數=2^h-1(h為樹的高度)可得o(2^n)。

遞迴的時間複雜度是:  遞迴次數*每次遞迴中執行基本操作的次數,所以時間複雜度是: o(2^n)

遞迴演算法空間複雜度分析:

遞迴最深的那一次所耗費的空間足以容納它所有遞迴過程。遞迴產生的棧偵是要銷毀的,所以空間也就釋放了,要返回上一層棧偵繼續計算+號後面的數,所以它所需要的空間不是一直累加起來的,之後產生的棧偵空間都小於遞迴最深的那一次所耗費的空間。

遞迴的深度*每次遞迴所需的輔助空間的個數 ,所以空間複雜度是:o(n)

6.1  非遞迴演算法分析

分析:假設最壞情況下,迴圈x次之後找到,則:2^x=n; x=logn(演算法中如果沒寫,log預設底數為2)

迴圈的基本次數是log2 n,所以: 時間複雜度是o(logn);

由於輔助空間是常數級別的所以:空間複雜度是o(1);

6.2 遞迴演算法複雜度分析

假設最壞情況下,迴圈x次之後找到,則:2^x=n; x=logn(演算法中如果沒寫,log預設底數為2)

遞迴的次數和深度都是log2 n,每次所需要的輔助空間都是常數級別的:

時間複雜度:o(log2 n);

空間複雜度:o(log2n )。

1

class

temp28

static

void

reset()

12static

intgetsum()

15private:16

static

intn;

17static

intsum;

18};

19int temp::n = 0;20

int temp::sum = 0;21

int solution_sum(int

n)28

intmain()

斐波那契數列 遞迴與非遞迴

首先來說下遞迴,遞迴的思想是大事化小。斐波那契數列 1,1,2,3,5,8,13,21.設f n 是第n個斐波那契數,當n 2,斐波那契數都為1 當n 2,那麼第f n 個斐波那契數就等於前兩個斐波那契數之和。遞迴的 實現 includeint fbnq int n int main 輸入10,得到...

python 遞迴與二分法

一 遞迴呼叫的定義 遞迴呼叫是函式巢狀呼叫的一種特殊形式,函式在呼叫時,直接或間接呼叫了自身,就是遞迴呼叫二 遞迴分為兩個階段 遞推,回溯 salary 5 salary 4 300 salary 4 salary 3 300 salary 3 salary 2 300 salary 2 salar...

二分查詢與斐波那契查詢

方法一 軸點取中點,逐步遞迴。演算法時間複雜度o log n 主要思路如下圖 不會執行 pre 對於該演算法,我們可以計算出迭代到底部所耗費的時間,計算結果如下圖所示。從圖中可以看出左邊遞迴和右邊遞迴所耗費的步數是不一樣的,那我我們是否可以找到一種演算法讓左邊迭代步數和右邊一致能,這樣能夠減少平均迭...