面試題的那些事(2)—斐波那契數列

斐波那契數列

1、寫一個函數,輸入n,求斐波那契數列的第n項。斐波納挈數列的定義如下:

wKiom1cCeQLD_FETAAAkmMx1hAg133.png

解法一:使用遞歸解決

long long RecurFibonacci(unsigned int n)
{
	if (n <= 0)
	{
		return 0;
	}
	if (n == 1)
	{
		return 1;
	}
	return RecurFibonacci(n - 1) + RecurFibonacci(n - 2);
}

分析:思路簡單理解,但是效率很低,面試官不一定會喜歡。因爲在進行遞歸時,會重複的計算。


解法二:非遞歸的解法(面試官期待的解法)

long long Fibonacci(unsigned int n)
{
	long long fib[2] = { 0,1 };
	if (n < 2)
	{
		return fib[n];
	}

	long long fibOne = 0;//保留Fibonacci(n-2)
	long long fibTwo = 1;//保留Fibonacci(n-1)
	long long fibN = 0;//第n個Fibonacci序列的結果
	for (unsigned int i = 2; i <= n; i++)
	{
		fibN = fibOne + fibTwo;
		fibOne = fibTwo;
		fibTwo = fibN;
	}
	return fibN;
}

分析:程序的可讀性雖然比較差,但是其效率很高。


測試代碼:

#include<iostream>
#include<Windows.h>

using namespace std;

int main()
{
	int start = GetTickCount();//從操作系統啓動所經過(elapsed)的毫秒數
	RecurFibonacci(40);
	int end = GetTickCount();
	cout <<"遞歸解法:"<< end - start << endl;

	start = GetTickCount();
	Fibonacci(40);
	end = GetTickCount();
	cout << "非遞歸解法:" << end - start << endl;
	getchar();
	return 0;
}

wKiom1cCeT6yGhocAAAbvgXvPTg406.png

2、跳臺階

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

解法分析:

最簡單的情況:

如果只有1級臺階,那麼顯然只有一種跳法。如果有2級臺階,那麼則會有2種跳法:一種是分兩次跳,每次跳1階;另外一種則是一次跳2級。

一般情況:

當n大於2時,第一次跳的時候有兩種選擇:一種是第一次只跳1階,此時的跳法就是f(n-1),另外一種跳法就是第一次跳2階,然後此時的跳法就是f(n-2)。所以總的次數就是f(n)=f(n-1)+f(n-2);很明顯此時是一個斐波那契數列。

long long jumpFloor( unsigned int number) 
{

	unsigned int jump[2] = { 0,1 };
	if (number < 2)
	{
		return jump[number];
	}

	long long jumpOne = 1;
	long long jumpTwo = 1;
	long long jumpN = 0;
	//n>2時爲斐波那契數列
	//跳一階則方法爲jumpFloor(n-1)
	//跳兩階則方法爲jumpFloor(n-2)

	for (unsigned int i = 2; i <= number; i++)
	{
		jumpN = jumpOne + jumpTwo;
		jumpOne = jumpTwo;
		jumpTwo = jumpN;
	}
	return jumpN;
}

3、變態跳臺階

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

解法分析:

使用數學歸納法:

1)當n爲1的時候,只有1種跳法

2)當n爲2的時候,可以有(1,1)和(2)共2種跳法

3)當n爲3的時候,可以有(1,1,1)、(1,2)、(2,1)、(3)共4種跳法

4)當n爲4的時候,可以有(1,1,1,1)、(1、2、1)、(1、3)、(1、1、2)、(2,1,1)、(2,2)、(3,1)、(4)共8種跳法

.......

由數學歸納法得f(n)=2的(n-1)次方。

long long jumpFloorII(unsigned int number) {
	if (number <= 0)
	{
		return 0;
	}
	return pow(2, number - 1);
}

4、矩形覆蓋

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

解法分析:

假設當n爲1的時候,只有1種覆蓋方法

當n>2時,覆蓋大矩形的最左邊時有2種覆蓋方法:當豎着放的時候右邊還剩下2*(n-1)個區域,此時的覆蓋方法爲f(n-1);當橫着放的時候,那麼最左下角也必須橫着放,那麼右邊還剩下2*(n-2)個矩形,此時的方法爲f(n-2);總的方法爲f(n)=f(n-1)+f(n-2),又是斐波納挈數列。


long long rectCover(unsigned int number) {
	if (number < 1)
	{
		return 0;
	}
	long long stepOne = 0;
	long long stepTwo = 1;
	long long step = 0;
	for (unsigned int i = 1; i <= number; i++)
	{
		step = stepOne + stepTwo;
		stepOne = stepTwo;
		stepTwo = step;
	}
	return step;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章