一、遞歸
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;
}