1、算法學習筆記--遞歸與分治

一、遞歸
1、遞歸的概念
直接或間接的調用自身的算法稱爲遞歸算法。
用函數自身給出定義的函數稱爲遞歸函數。
二要素:邊界條件和遞歸方程

1.1階乘函數
當n=0,n!=1;
當n>0,n!=n*(n-1)!

#include<iostream> 
using namespace std;
int factorial(int n)
{
	if(n==0) return 1;            /*邊界條件*/
	else return n*factorial(n-1); /*遞歸方程*/
}
int main()                      /*以下算法調用過程類似,不再給出*/
{
	int result;
	int n; 
	while(cin>>n)
	{
		result = factorial(n);
		cout<<result<<endl;
	}
	return 0;
}

1.2 Fibonacci 數列
當n=0||n=1,F(n)=1;
當n>=2,F(n)=F(n-1)+F(n-2)

int Fibonacci(int n)
{
	if(n<=1) return 1;
	return Fibonacci(n-1)+Fibonacci(n-2);
}

1.3 排列問題–全排列
設·R={r1,r2,r3,…,rm}爲要進行全排列的m個元素,Perm(R)爲集合R的全排列,(ri)Perm(Ri)表示全排列Perm(Ri)的每一個排列加上前綴ri的排列。
當m=1,Perm(R)=(r);
當m>1,Perm(R)由(r1)Perm(R1)、(r2)Perm(R2)、…、(rn)Perm(Rn)組成。
這裏寫圖片描述

m爲數組長度減1,k初始值爲0
void perm(int list[],int k,int m)
{
	int i;
	int t;
	if(k==m)
	{
		for(i=0;i<=m;i++)
		{
			cout<<list[i]<<" ";
		}
		cout<<endl;
	}
	else
	{
		for(i=k;i<=m;i++)
		{
			t=list[k];list[k]=list[i];list[i]=t;
			/*swap(list[k],list[i]);*/
			perm(list,k+1,m);
			/*swap(list[k],list[i]);*/
			t=list[k];list[k]=list[i];list[i]=t;
		}
	}
}

1.4 整數劃分
將正整數n表示爲一系列正整數之和,稱爲正整數的劃分。
q(n,m)表示最大加數n不大於m的劃分個數。
①當m=1||n=1時,q(n,1)=q(1,m)=1;
②當n<m時,q(n,m)=q(n,n);
③當n=m時,q(n,n)=1+q(n,n-1);
④當n>m>1時,q(n,m)=q(n,m-1)+q(n-m,m);

int q(int n,int m)
{
	if(n==1||m==1) return 1;
	if(n<m) return q(n,n);
	if(n==m) return 1+q(n,n-1);
	if(n>m) return q(n,m-1)+q(n-m,m);
}

二、分治算法
2.1、棋盤覆蓋

int tile = 1;       //全局變量 
int Board[128][128]; //全局變量 
void ChessBoard(int lr,int lc,int sr,int sc,int size)
{  //lr:棋盤左上角行號,lc:棋盤 左上角列號,sr:特殊方格行號,sc:特殊方格列號,size:棋盤大小 
	if(size==1) return;
	int t = tile++;
	size = size/2;
	//左上角棋盤 
	if(lr+size-1>=sr && lc+size-1>=sc){
		ChessBoard(lr,lc,sr,sc,size); //特殊方格在左上角 
	}
	else{                //特殊方格不在左上角,覆蓋左上角棋盤的右下角方格 
		Board[lr+size-1][lc+size-1] = t;
		ChessBoard(lr,lc,lr+size-1,lc+size-1,size);
	}
	//右上角棋盤 
	if(lr+size-1>=sr && lc+size-1<sc){
		ChessBoard(lr+size-1,lc+size-1,sr,sc,size); //特殊方格在右上角棋盤 
	}
	else{                                         //特殊方格不在 右上角 
		Board[lr+size-1][lc+size] = t;             //覆蓋右上角棋盤的左下角方格 
		ChessBoard(lr,lc+size,lr+size-1,lc+size-1,size);
	}
	//左下角棋盤如上 
	if(lr+size-1<sr && lc+size-1>=sc){
		ChessBoard(lr+size-1,lc,sr,sc,size);
	}
	else{
		Board[lr+size][lc+size-1] = t;
		ChessBoard(lr+size,lc,lr+size,lc+size-1,size);
	}
	//右下角棋盤如上 
	if(lr+size-1<sr && lc+size-1<sc){
		ChessBoard(lr+size,lc+size,sr,sc,size);
	}
	else{
		Board[lr+size][lc+size] = t;
		ChessBoard(lr+size,lc+size,lr+size,lc+size,size);
	}
}

2.2、排序
①合併排序:時間複雜度爲O(nlogn)
②快速排序:時間複雜度爲O(nlogn)

2.3、二分搜索法:時間複雜度爲O(logn)

int BinarySearch(int list[],int n,int x)
{
	int left=0;
	int right=n-1;
	int middle;
	while(left<=right)
	{
		middle=(left+right)/2;
		if(x<list[middle]) right=middle-1;
		if(x==list[middle]) return middle;
		if(x>list[middle]) left=middle+1;
	}
	return -1;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章