題目一:寫乙個函式,輸入n,求斐波那契(fibonacci)數列的第n項。斐波那契數列數列的定義如下:除了面試官直接要求程式設計實現斐波那契數列之外,還有不少面試題可以看成是斐波那契數列的應用,比如:f[n]=f[n-1]+f[n-2],且f[1]=1,f[2]=1。
首先我們考慮最簡單的情況。如果只有一級台階,那顯然只有一種跳法。如果有2級台階,那就有兩種跳法了:一種是分兩次跳,沒跳1級;另外一種就是一次跳2級。
接著我們再來討論一般情況。我們把n級台階時的跳法看成時n的函式,記為f(n)。當n>2時,第一次跳的時候就有兩種不同的選擇:
(1)第一次只挑1級,此時跳法數目等於後面剩下的n-1級台階的跳法數目,即為f(n-1);
(2)選擇第一次跳兩級,此時跳法數目等於後面剩下的n-2級台階的跳法數目,即為f(n-2)。
因此n級台階的不同跳法的總數f(n) = f(n-1) + f(n-2)。分析到這裡我們不難看出這實際上就是斐波那契數列了。
類似的題目還有骨牌覆蓋問題,演算法-骨牌覆蓋問題(矩陣快速冪求fibonacii)效率很低的遞迴演算法我們的教科書上反覆用這個問題來講解遞迴函式,並不能說明遞迴的解法最適合這道題目。
long
long fibonacci(unsigned
int n)
if(n == 1)
return fibonacci(n-1) + fibonacci(n-2);
}
優點:形式簡潔,便於人理解
缺點:雖說遞迴法以空間換時間,但一旦n變大,它的速度的確比非遞迴法慢得多,例如對n=40,測試遞迴法所用時間為8~9s;而非遞迴法只需要遠不到1s。
原因是,遞迴過程中,系統建立堆疊來儲存上一層狀態資訊, 和退棧獲取還原系統狀態都要有開銷的.系統做的事情不少, 所以效率要低.
例如,f(5)的話,實際上會呼叫這個函式15次,有15個臨時棧區,試想f(100)有多嚇人。。。一般來說到f(40)以後,普通計算機基本上就不可能計算出來了。
通項公式演算法
//使用通項公式fib(n) = [(1+√5)/2]^n /√5 - [(1-√5)/2]^n /√5
#define root_of_five sqrt(5.0)
long
double fibonacci(unsigned
int n)
迭代演算法上述遞迴**之所以慢是因為重複計算太多,我們只要想辦法避免重複計算就行了。比如我們可以把已經得到的數列中間項儲存起來,如果下次需要計算的時候我們先查詢一下,如果前面已經計算過就不用再重複計算了。
更簡單的方法是從下網上算,首先根據f(0)和f(1)算出f(2),再根據f(1)和f(2)算出f(3)…….以此類推就可以算出第n項了。很容易理解,這種思路的時間複雜度是o(n)。
#include
using
namespace
std;
long
long fibonacci(unsigned n)
; if(n < 2)
return result[n];
long
long fibnminusone = 1;
long
long fibnminustwo = 0;
long
long fibn = 0;
for(unsigned
int i = 2; i <= n; i++)
return fibn;
}int main()
矩陣快速冪演算法時間複雜度o(logn)但不夠實用的解法
程式1:
//2*2矩陣結構體
struct matrix2by2
//資料成員
long
long m00;
long
long m01;
long
long m10;
long
long m11;
};//兩個2*2矩陣乘法
matrix2by2 matrix_multiply(const matrix2by2 matrix1, const matrix2by2 matrix2)
//矩陣的快速冪演算法
matrix2by2 matrix_fast_power(unsigned
int n)
else
if (n % 2 == 1)
return matrix;
}//斐波那契數列計算式
long
long p_fibonacci(unsigned
int n)
程式2:
#include
using namespace std;
const
int mod = 19999997;
struct matrix
matrix &operator = (matrix &data)
};long
long fastfibonacci(long n)
; matrix base = ;
matrix temp;
n++;
while(n)
temp = base;
base = base*temp;
n >>=1;
}return res.d;
}int main()
解法比較用不同的方法求解斐波那契數列的時間效率大不相同。
使用哪種方法根據實際情況確定,從時間複雜度上來說o(通向公式法)《o(快速冪法)《o(迭代法)《o(遞迴法)。
第一種基於遞迴的解法雖然直觀但是時間效率很低,在實際軟體開發中不會用這種方法,也不可能得到面試官的青睞。
第二種防方法結果不會很準確,但至少能說明問題。
第三種方法把遞迴的演算法用迴圈實現,極大地提高了時間效率。
第四種方法把斐波那契數列轉換成求矩陣的乘方,是一種很有創意的演算法。雖然我們可以用o(logn)求得矩陣的n次方,但由於隱含的時間常數較大,很少會有軟體採用這種演算法。另外實現這種解法的**也很複雜,不太適用面試。因此第三種方法不是一種實用的演算法,不過應聘者可以用它來展現自己的知識面。
完整的程式**:
#include
#define root_of_five sqrt(5.0)
using
namespace
std;
//遞迴方式
long
long r_fibonacci(unsigned
int n)
//通項公式演算法
long
double t_fibonacci(unsigned
int n)
//迭代方式
long
long i_fibonacci(unsigned
int n)
; if (n < 2)
return result[n];
long
long fib_one = 0;
long
long fib_two = 1;
long
long fibn = 0;
for (unsigned
int i = 2; i <= n; ++i)
return fibn;
}//矩陣快速冪演算法
//2*2矩陣結構體
struct matrix2by2
//資料成員
long
long m00;
long
long m01;
long
long m10;
long
long m11;
};//兩個2*2矩陣乘法
matrix2by2 matrix_multiply(const matrix2by2 matrix1, const matrix2by2 matrix2)
//矩陣的快速冪演算法
matrix2by2 matrix_fast_power(unsigned
int n)
else
if (n % 2 == 1)
return matrix;
}//斐波那契數列計算式
long
long p_fibonacci(unsigned
int n)
int main()
system("pause");
return
0;}
斐波那契數列 斐波那契數列python實現
斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...
迴圈斐波那契數列 斐波那契數列應用
什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...
斐波那契數列
1 題目描述 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項。斐波那契數列的定義如下 輸入 輸入可能包含多個測試樣例,對於每個測試案例,輸入包括乙個整數n 1 n 70 輸出 對應每個測試案例,輸出第n項斐波那契數列的值。2 這是九度上的乙個題,要求時間限制1秒,整數的...