🤳概念
- 递归边界 —— 分解的尽头
- 递归式(递归调用) —— 将原问题分解为若干个子问题(分治)
递归多半会与深度广度优先搜索结合考察
因此切记要自己动手写全递归过程!!!
🐱🚀例题
//简单款
//Fibonacci F0 = F1 = 1 F(n) = F(n-1) + F(n-2)
int Fibonacci(int index){
if(index == 0 || index == 1) return 1;
else return Fibonacci(n-1)+Fibonacci(n-2);
}
全排列
//最经典 全排列 Full-Permutation
const int maxn = 11;
int n;
int P[maxn],hashTable[maxn] = {false};
//P is output of full permutation
//generate permutation start with nuber index;
void generateF(int index){
//recursion borden
if(index == n+1){
for(int i=1;i<=n;i++){
printf("%d ",P[i]);
}
printf("\n");
return;
}else
{
for(int x=1;x<=n;x++){
//对每个排列位(index)进行给定数列遍历,对每个递归分支,都用独立hashmap
//来记录该遍历数是否已插入排列
//递归边界是当下一递归式参数越界时,说明排列完成,输出并开始大返回
//递归边界“到达后”逐步返回重置hashmap达到独立hashmap
//注意全排列和组合的区别
if(hashTable[x]==false){
P[index] = x; //notice the diff between index & x
hashTable[x] = true;
generateF(index+1);
hashTable[x] = false;
}
}
}
}
main->generateP(1);
example
input:
n = 3
output:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
n皇后问题
假如用组合来枚举(n^2棋盘的n枚棋子)情况->筛选;需要C(n*n,n),当n为8就是54502232次
因此用递归按行DFS,产生1-n的全排列,记录每个合法排列,需要n! 当n为8就是40320
bool validQueen(){
for(int i = 1; i <= n; i++){
for(int j = i+1; j<=n; j++){
if(abs(P[i] - P[j]) == abs(i - j) || P[i] == P[j]){
return false;
}
}
}
return true;
}
void generateP(int index){
if(index == n+1 && validQueen()){
for(int i = 1; i <= n; i++){
printf("%d ",P[i]);
}
printf("\n");
count++;
return;
}
//else are the same
}
}
组合
//生成C(n,k)全组合
//除了用到递归 还有 深度优先搜素
int n,k,sum,res;
int P[22] = {0};
int A[22] = {0};
void generateP(int curP,int curA){
if(curP == k+1){
//同样定义递归边界
//if(check(sum)) res++;
for(int i = 1; i <= k; i++){
printf("%d ",P[i]);
}
printf("\n");
return;
}
for(int i = curA; i <= n;i++){
//精髓在i = curA,实现排列的C(n,1)->C(n-1,1)->...选取
//初始逻辑为 通过gP(0,0) 产生 gp(1,1)-gp(1,n) 并以此深度搜索
//if判断在于控制只让gp(0,0)产生分支, 否则gp(0,1)->gp(1,2)
//等同于gp(0,0)->gp(1,2)
P[curP] = A[i];
if(curP == 0 && i != 0) return;
generateP(curP+1,i+1);
//sum -= A[i];
}
}