第4章 入门篇(2)——算法初步(3)
4.3 递归
4.3.1 分 治
分治的全称为“分而治之”。分治法将原问题划分成若干个规模较小而结构与原问题相同或相似的问题,然后分别解决这些子问题,最后合并子问题的解,即可得到为原问题的解。分治法有三个步骤①分解 ②解决 ③合并。分治法作为一种算法思想,即可以使用递归的手段去实现,也可以通过非递归的手段去实现
注:分治法分解出的子问题应当是相互独立、没有交叉的。如果存在两个子问题有相交部分,那么不应当使用分治法解决。
减治(decrease and conquer):子问题个数为1的情况
分治(divide and conquer):子问题个数大于1的情况
对n的阶乘的求解过程体现了减治的思想,对Fibonacci数列的求解过程体现了分治的思想
4.3.2 递 归
递归在于反复调用自身函数,但是每次把问题范围缩小,直到范围缩小到可以直接得到边界数据的结果,然后再返回的路上求出对应的解。递归很适合用来实现分治思想。递归逻辑一般有两个重要的概念:①递归边界 ②递归式(或称递归调用) 递归式是将原问题分解为若干个子问题的手段,递归边界则是分解的尽头。
- 使用递归求解n的阶乘
n!=1 *2 *3 *…*n,这个式子写成递推形式就是n!=(n-1)!*n,以F(0)=1作为递归边界。
#include<iostream>
using namespace std;
int F(int n){
if(n==0) return 1; //递归边界
else return F(n-1)*n;
}
int main(){
int n;
scanf("%d",&n);
printf("%d\n",F(n));
return 0;
}
- 求Fibonacci数列的第n项
Fibonacci数列(斐波那契数列)是满足F(0)=1,F(1)=1,F(n)=F(n-1)+F(n-2)(n>=2)的数列。所以递归边界为F(0)=1,F(1)=1,且递归式为F(n)=F(n-1)+F(n-2)(n>=2)
#include <iostream>
using namespace std;
int F(int n){
if(n==0||n==1) return 1;
else return F(n-1)+F(n-2);
}
int main(){
int n;
scanf("%d",&n);
printf("%d\n",F(n));
return 0;
}
全排列
一般把1~n这n个整数按某个顺序摆放的结果称为这n个整数的一个排列,而全排列指这n个整数能形成的所有排列。
#include<iostream>
using namespace std;
const int maxn=11;
int n,p[maxn],hashTable[maxn]={false};
void generateP(int index){
if(index==n+1){
for(int i=1;i<=n;i++){
printf("%d",p[i]);
}
printf("\n");
return;
}
for(int x=1;x<=n;x++){
if(hashTable[x]==false){
p[index]=x;
hashTable[x]=true;
generateP(index+1);
hashTable[x]=false;
}
}
}
int main(){
n=3;
generateP(1);
return 0;
}