C语言求全排列

相信大家都遇到过,包括各种算法比赛,经常会遇到求一组数据或者单个事物或者多个事物全排列和组合的问题,那么我们该如何求呢?下面我分享给大家排列组合:
一:全排列

#include<stdio.h>
#include<string.h>
void fullPermutation(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; }
		fullPermutation(a, k+1);
		//回溯 :把上一级改变的再改变过来,防止下次递归改变a的值时,已经不是初始的a
		{ t = a[k]; a[k] = a[i]; a[i] = t; }
	}
}
int main(){
	char a[4] = {'A', 'B', 'C'};               //初始化字符数组a
	fullPermutation(a, 0); 
	return 0;
}

二:组合问题

1.不重复的情况:
例如ABCDE,让你从里面选出3个,问你一共有多少种可能,我们可以直接递归进行列举一共有多少种。下面看代码:

#include<stdio.h>
//元素个数不重复 
int combination(int m,int n){
/*
我们一直从堆里拿球,当拿到,堆里的球和我们想要拿的球数相同,只要一种情况。 
当我们从堆里取出0个时,从数学角度上,这也是一种取法。
*/
	if(n == m || n == 0) return 1;                         
/* 
假设堆里有个特殊的球,两种情况:要么这个球就是我们要取的,那么我们从m-1个球里再取n-1个,
如果不是,那么我们从m-1个球里取出n个,一直这样递归下去。
*/
	return combination(m-1, n) + combination(m-1, n-1);      
}
int main(){
	printf("%d",combination(5, 3));       //5代表ABCDE这5个字母,3代表从中取三个。
	return 0;
}

2.重复的情况:

例如AABBBC ,让你从这些字母中选出三个进行组合,你肯定不能枚举,这样你会发现打印出来有重复的。因为元素有相同的。所以这个时候要选择另外一种方式:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
/*
data:不动,限制条件 
x:取法 
k:当前考虑的位置 
goal:距离目标的剩余名额 
注意: 
这是针对取的元素中有相同的 
*/
int min(int a, int b){
    return (a > b) ? b : a;
}
void work(int x[]){
	int i;
	for(i = 0; i < 3; i++){
		printf("%d", x[i]);
	}
	printf("\n");
}
void combination(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;
		combination(data, x, k+1, goal - i);
	}
	x[k] = 0;//回溯 
} 
int main(){
	int i;
	int data[3] = {2, 3, 1};    //每个元素的最大个数 
	int x[3];                   //每个元素取几个 
	combination(data, x, 0, 3);
	return 0;
} 

如果喜欢我的博客,点个赞吧!!!!!!!!!!!

  • 14
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值