在面試中我們可能會遇到青蛙跳的問題:一隻青蛙一次可以跳上一級臺階,或者跳上二級臺階。那麼如果總共有N級臺階,問這隻青蛙總共有多少種跳法?
首先,我們考慮最簡單的情況,如果只有一級臺階,那顯然青蛙只有一種跳法。如果只有二級臺階,那麼青蛙就有兩種跳法,一種是每次跳一級,總共跳二次,另一種就是直接跳二級。
接下來,再來看N級的(N大於2)的情況。我們先把N級臺階的跳法看做一個N的函數,記爲f(N)。考慮N>2時,第一次跳就有兩種跳法,一種是第一次只跳一級,此時跳法數就是後面剩下的N-1級臺階的跳法數,即爲f(N-1);另一種則是第一次跳二級,那麼此時的跳法數就是後面剩下的N-2級臺階的跳法數,即爲f(N-2)。所以,N級臺階的跳法總數就是f(N)=f(N-1)+f(N-2)。顯然這就是一個N>0的斐波那契數列。
C++實現遞歸解法
#include<iostream>
using namespace std;
long long RecursiveFibonacci(unsigned int n)
{
if(n == 1 || n == 2)
return n;
return RecursiveFibonacci(n-1) + RecursiveFibonacci(n-2);
}
int main()
{
cout << "RecursiveFibonacci(1)=" << RecursiveFibonacci(1) << endl;
cout << "RecursiveFibonacci(2)=" << RecursiveFibonacci(2) << endl;
cout << "RecursiveFibonacci(3)=" << RecursiveFibonacci(3) << endl;
cout << "RecursiveFibonacci(5)=" << RecursiveFibonacci(5) << endl;
cout << "RecursiveFibonacci(10)=" << RecursiveFibonacci(10) << endl;
cout << "RecursiveFibonacci(50)=" << RecursiveFibonacci(50) << endl;
cout << "RecursiveFibonacci(100)=" << RecursiveFibonacci(100) << endl;
}
很顯然,遞歸實現效率是非常低的,其時間複雜度是n的指數級。因爲遞歸存在着大量的重複計算,大家也可以自己跑代碼試試,遞歸去計算n=50就非常慢了。
所以,優化思路就是從前往後計算,先根據f(1)和f(2)算f(3),在根據f(2)和f(3)算f(4),以此類推算出f(N)。其時間複雜度是O(n)。
C++實現非遞歸解法
#include<iostream>
using namespace std;
long long NonRecursiveFibonacci(unsigned int n)
{
if(n == 1 || n == 2)
return n;
long long n1 = 1;
long long n2 = 2;
long long result = 0;
for (unsigned int i = 3; i <= n; i++)
{
result = n1 + n2;
n1 = n2;
n2 = result;
}
return result;
}
int main()
{
cout << "NonRecursiveFibonacci(1)=" << NonRecursiveFibonacci(1) << endl;
cout << "NonRecursiveFibonacci(2)=" << NonRecursiveFibonacci(2) << endl;
cout << "NonRecursiveFibonacci(3)=" << NonRecursiveFibonacci(3) << endl;
cout << "NonRecursiveFibonacci(5)=" << NonRecursiveFibonacci(5) << endl;
cout << "NonRecursiveFibonacci(10)=" << NonRecursiveFibonacci(10) << endl;
cout << "NonRecursiveFibonacci(50)=" << NonRecursiveFibonacci(50) << endl;
cout << "NonRecursiveFibonacci(100)=" << NonRecursiveFibonacci(100) << endl;
}