[递归] 组合2 - 从自然数1,2,...,n中任取r个数的所有组合

版权声明:本文为博主原创文章,若有错误之处望大家批评指正!转载需附上原文链接,谢谢! https://blog.csdn.net/summer_dew/article/details/83315100

【问题】利用递归方法找出从自然数1,2,…,n中任取r个数的所有组合
【例如】n=5,r=3,所有组合为:
在这里插入图片描述

方法一

【思路】

  1. 抽象问题:1,…,n中选r --> f(n,r)
  2. 从边界n考虑,n要么取,要么不取 --> f(n,r) = f(n-1, r) + f(n-1, r-1)
  3. 退出条件:r==0时,就已经选完了
  4. 异常条件:n<r的时候
int a[50];

void f(int n,int r,int m) {
	int i;

	if (n<r) return ;

	if (r==0) {
		for (i=0; i<m; i++) printf("%d", a[i]);
		printf("\n");
	} else {
		//选n
		a[m] = n;
		f(n-1, r-1, m+1);
		//不选n
		f(n-1, r, m);
	}
}

方法二

【代码】

// 从1-n的数字中选r个数字
//	目前选的一个放入a[m]位置中
void C(int n, int r, int a[], int m) {
	int i;
	if (r==0) { //选完了
		//输出
		for (i=0; i<m; i++) printf("%d", a[i]);
		printf("\n");
	} else {
		// 在[r,n]的范围内选一个数字放入a[m]
		for (i=n; i>=r; i--) {
			a[m] = i;
			C(i-1, r-1, a, m+1);
		}
	}
}

【理解】用树状的形式输出递归树(先序)
树状的方式类似于这种https://blog.csdn.net/summer_dew/article/details/82937941
在这里插入图片描述

完整代码

方法一:

#include<stdio.h>

int a[50];

void f(int n,int r,int m) {
	int i;

	if (n<r) return ;

	if (r==0) {
		for (i=0; i<m; i++) printf("%d", a[i]);
		printf("\n");
	} else {
		//选n
		a[m] = n;
		f(n-1, r-1, m+1);
		//不选n
		f(n-1, r, m);
	}
}

int main() {
	int n,r;
	while (1) {
		printf("输入n与r,空格分割\n>>> ");
		scanf("%d%d", &n, &r);
		f(n, r, 0);
		printf("\n");
	}
	return 0;
}

方法二:

#include<stdio.h>

// 从1-n的数字中选r个数字
//	目前选的一个放入a[m]位置中
void C(int n, int r, int a[], int m) {
	int i;

	// 以树状输出递归树
	/*
	for (i=0; i<m; i++) {
		printf("  ");
	}
	printf( "C(%d,%d, '" , n,r);
	for (i=0; i<m; i++) {
		printf("%d ", a[i]);
	}
	printf("', %d)",m );
	printf("\n");
	*/

	if (r==0) { // 选完了
		// 输出
		for (i=0; i<m; i++) printf("%d", a[i]);
		printf("\n");
	} else {
		// 在[r,n]的范围内选一个数字放入a[m]
		for (i=n; i>=r; i--) {
			a[m] = i;
			C(i-1, r-1, a, m+1);
		}
	}
}

int main() {
	int n,r;
	int a[50];
	while (1) {
		printf("输入n与r,空格分割\n>>> ");
		scanf("%d%d", &n, &r);
		C(n, r, a, 0);
		printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/summer_dew/article/details/83315100