问题:求n个数中K个数的组合,假设函数原型为 int combination(int n,int k),其中 n的范围为 1……n, 例如:combination(5,3) 要求输出:543、542、541、531、532、521、432、431、421、321如果输出时有用到数组,其空间需要在开始动态分配好,结束时释放。
还是利用递归,关键是要记得:c(m,k) = c(m -1 , k- 1) + c(m - 2, k - 1) + ...+ c(k - 1.k - 1)
# include
# define MAXN 100
int a[MAXN];
/**
* 组合问题
*问题描述:找出从自然数1、2、……、m中任取k个数的所有组合。
*/
void comb(int m, int k) {
int i, j;
for (i = m; i >= k; i--) {
a[k] = i;
if (k > 1)
comb(i - 1, k - 1);
else {
for (j=a[0];j>0;j--)
printf("%4d",a[j]);
printf("\n");
}
}
}
int main() {
a[0] = 3;
// int a[] = {1,2,3,4,5};
comb(5, 3);
return 0;
}
5 4 3
5 4 2
5 4 1
5 3 2
5 3 1
5 2 1
4 3 2
4 3 1
4 2 1
3 2 1
还有一种思路非常巧妙,如下:
http://hi.baidu.com/%D7%D4%D3%C9%B5%C6%CB%FE/blog/item/d6310e6e2ffb2edd80cb4a48.html
4)利用数组
定义:从n个数中取出m个数的组合。
实现机理:先创建一个字符串数组,其下标表示 1 到 n 个数,数组元素的值为1表示其下标代表的数被选中,为0则没选中。
然后初始化,将数组前 m 个元素置 1,表示第一个组合为前 m 个数。
然后从左到右扫描数组元素值的 10 组合,找到第一个 "10" 后交换 1 和 0 的位置,变为 01,而后将该10组合前的1和0重新组合(1放在前边,其个数为10组合前1的个数,0放在后边,其个数为10前0的个数,而后接10的倒转组合01)。当m 个 1 全部移动到最右端时,就得到了最后一个组合。
例如求 5 中选 3 的组合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5