相信大家都遇到过,包括各种算法比赛,经常会遇到求一组数据或者单个事物或者多个事物全排列和组合的问题,那么我们该如何求呢?下面我分享给大家排列组合:
一:全排列
#include<stdio.h>
#include<string.h>
void f(char a[],int k){
int i,length;
length=strlen(a); //计算字符串的长度
if(k==length-1){
printf("%s",a); //打印字符数组a
printf("\n");
return ;
}
char t;
for(i=k;i<length;i++){
{
//试探
t=a[k]; a[k]=a[i];a[i]=t;
}
f(a,k+1);
{
//回溯 :把上一级改变的再改变过来,防止下次递归改变a的值时,已经不是初始的a
t=a[k]; a[k]=a[i];a[i]=t;
}
}
}
int main(){
char a[4]={'A','B','C'}; //初始化字符数组a
f(a,0);
return 0;
}
二:组合问题
1.不重复的情况:
例如ABCDE,让你从里面选出3个,问你一共有多少种可能,我们可以直接递归进行列举一共有多少种。下面看代码:
#include<stdio.h>
//元素个数不重复
int f(int m,int n){
if(n==m){ //我们一直从堆里拿球,当拿到,堆里的球和我们想要拿的球数相同,只要一种情况。
return 1;
}
if(n==0){ //当我们从堆里取出0个时,从数学角度上,这也是一种取法。
return 1;
}
/*
假设堆里有个特殊的球,两种情况:要么这个球就是我们要取的,那么我们从m-1个球里再取n-1个,如果不是,那么我们从m-1个球里取出n个,一直这样递归下去。
*/
return f(m-1,n)+f(m-1,n-1);
}
int main(){
printf("%d",f(5,3)); //5代表ABCDE这5个字母,3代表从中取三个。
return 0;
}
```C
2.重复的情况:
例如AABBBC ,让你从这些字母中选出三个进行组合,你肯定不能枚举,这样你会发现打印出来有重复的。因为元素有相同的。所以这个时候要选择另外一种方式:
```c
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
/*
data:不动,限制条件
x:取法
k:当前考虑的位置
goal:距离目标的剩余名额
注意:
这是针对取的元素中有相同的
*/
int min(int a,int b){
if(a>b){
return b;
}
return a;
}
void work(int x[]){
int i;
for(i=0;i<3;i++){
printf("%d",x[i]);
}
printf("\n");
}
void f(int data[],int x[],int k,int goal){
int i;
if(k==3){
if(goal==0){
work(x);
}
return ;
}
for(i=0;i<=min(data[k],goal);i++){
x[k]=i;
f(data,x,k+1,goal-i);
}
x[k]=0;//回溯
}
int main(){
int i;
int data[3]={2,3,1}; //每个元素的最大个数
int x[3]; //每个元素取几个
f(data,x,0,3);
return 0;
}
如果喜欢我的博客,点个赞吧!!!!!!!!!!!