算法笔记练习 8.1 深度优先搜索(DFS) 问题 B: 【递归入门】组合的输出

算法笔记练习 题解合集

本题链接

题目

题目描述
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r < = n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。
现要求你不用递归的方法输出所有组合。
例如n = 5 ,r = 3 ,所有组合为:

1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5 

输入
一行两个自然数n、r ( 1 < n < 21,1 < = r < = n )。

输出
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,所有的组合也按字典顺序。

思路

受之前题目的影响,我先写了一个版本,把ans数组作为DFS的形参跟着递归一层层传递了,虽然这样写出来直观一点,但是递归的开销太大。于是又写了一个普通版本,也就是把数组写成全局变量。

在 codeup 上实测,全局变量的版本用时大约是形参版本的三分之一。

代码

全局变量版本

#include 
#include 
using namespace std;
int n, r;
vector<int> ans(22);
void DFS(int index, int cnt) {
	if (cnt == r) {
		for (int i = 0; i < r; ++i) {
			if (i > 0)
				putchar(' ');
			printf("%d", ans[i]); 
		}
		putchar('\n');
		return; 
	}
	if (index > n)
		return;
	ans[cnt] = index;
	DFS(index + 1, cnt + 1);
	DFS(index + 1, cnt);
} 
int main() {
	while (scanf("%d%d", &n, &r) != EOF)
		DFS(1, 0);
	return 0;
} 

形参版本

#include 
#include 
using namespace std;
int n, r;
void DFS(int index, vector<int> ans) {
	if (ans.size() == r) {
		for (int i = 0; i < ans.size(); ++i) {
			if (i > 0)
				putchar(' ');
			printf("%d", ans[i]); 
		} 
		putchar('\n'); 
		return;
	}
	if (index > n)
		return;
	ans.push_back(index); 
	DFS(index + 1, ans);
	ans.pop_back();
	DFS(index + 1, ans);
} 
int main() {
	while (scanf("%d%d", &n, &r) != EOF) {
		vector<int> ans;
		DFS(1, ans);
	}
	return 0;
}

你可能感兴趣的:(算法笔记)