遞歸與分治策略(一)---算法設計與分析

遞歸與分治策略(一)java

簡而言之,遞歸就是本身調用本身。算法

遞歸算法:直接或者間接地調用自身的算法。函數

遞歸函數:用函數自身給出定義的函數。性能

注意:每一個遞歸函數都必須有非遞歸定義的初始值,以確保遞歸函數完成計算。測試

下面經過兩個例子來介紹遞歸的特色spa

階乘函數code

階乘函數遞歸地定義爲:blog

n!=1   (n=0)   排序

或者   遞歸

n!=n(n-1)!  (n>0)

下面用一段簡單的Java代碼實現

這裏是遞歸實現:

public static int facterial(int n) {
		if (n == 0)
			return 1;
		else if (n < 0)
			return -1;//發生異常,退出
		else
			return n * facterial(n - 1);
	}

下面是迭代實現:

public static int f(int n) {
		if (n == 0)
			return 1;
		else if (n < 0)
			return -1;//發生異常,退出
		else {
			for (int i = n - 1; i >= 1; i--) {
				n *= i;
			}
			return n;
		}

	}

分析比較一下兩種實現方法:

遞歸實現:時間複雜度O(n);空間複雜度O(n)

迭代實現:時間複雜度O(n);空間複雜度O(1)

比較可知兩種實現的時間複雜度等價,空間複雜度遞歸佔用的略大一下,可是代碼的結構清晰度遞歸更清晰一些。

下面進行第二個例子的講解

2 Fibonacci數列

Fibonacci數列的遞歸定義爲

F(n)=1   (n=0,1)

或者

F(n)=F(n-1)+F(n-2)    (n>1)

下面用一段簡單的Java代碼實現

這裏是遞歸實現:

public static int fibonacci(int n ){
		if(n<0)
			return -1; //發生異常,退出
		else if(n<=1)
			return 1;
		else 
			return fibonacci(n-1)+fibonacci(n-2);
	}

下面是迭代實現:

public static int F(int n){
		if(n<0)
			return -1; //發生異常,退出
		else if(n<=1)
			return 1;
		else {
			int f0=1,f1=1,fx=0;
			for(int i=2;i<=n;i++){
				fx=f0+f1;
				f0=f1;
				f1=fx;
			}
			return fx;
		}
	}

分析比較一下兩種實現方法:

遞歸實現:時間複雜度O(1.618n次方);空間複雜度O(n)

迭代實現:時間複雜度O(n);空間複雜度O(1)

比較可知遞歸實現的時間複雜度已經很是大了,空間複雜度遞歸佔用的略大一下,可是代碼的清晰度遞歸更清晰一些。而真正使用起來遞歸實現的代碼是無用代碼,用n=40這個數測試一下便知,遞歸實現的耗時太長了,有興趣的能夠測試一下。

下面概括一下遞歸算法的特色:

1.簡單(結構清晰,可讀性強)

2.性能較低(相比較迭代而言)

性能較低的緣由有如下兩點:

需遞歸調用工做棧支持(沒法避免)

有可能出現子問題重疊現象(必須盡力避免)

 

這裏遞歸的主要知識點就講完了,下面介紹一下文章標題的分治法。

分治法的基本思想:

(容易)分解->遞歸->(容易)合併

分解:講一個大規模的問題分解爲多個規模較小的子問題,須要注意的是子問題必須互相獨立而且與原問題相同。

這裏用一個例子進行講解:歸(合)並排序。

這裏留在下一篇文章介紹,睡覺咯,今天學到了這些,和你們分享一下,感謝你們的支持。

相關文章
相關標籤/搜索