全排列:
计算出n个整数的全排列种数,并输出这所有的排列。
假设这n个整数是 1 ~ n
Input
一个整数 n ( 1 ≤ n ≤ 9 )
Output
第一行输出全排列的个数a,接下来a行,每行一个排列。
Sample Input
3
Sample Output
6
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
方法一:
#include<stdio.h>
int a[10],b[10],n;
void permutation_dfs(int x)
{
if(x==n+1){
for(int i=1;i<=n;i++){
printf("%d ",a[i]);
}
printf("\n");
return;
}
for(int i=1;i<=n;i++){
if(b[i]==0){
a[x]=i;
b[i]=1;
permutation_dfs(x+1);
b[i]=0;
}
}
return;
}
int main()
{
while(~scanf("%d",&n))
{
int sum=1;
for(int i=n;i>1;i--){
sum=sum*i;
}
printf("%d\n",sum);
permutation_dfs(1);
}
return 0;
}
方法二:交换法
全排列就是从第一个数字起每个数分别与它后面的数字交换
#include<bits/stdc++.h>
using namespace std;
void swap(int &a, int &b) {
int tem = a;
a = b;
b = tem;
}
void dfs(int *m, int s, int e) {
if (s == e) {
for (int i = 0; i <= e; i++) {
cout << m[i] << ' ';
}
cout << endl;
return;
}
for (int i = s; i <= e; i++) {
swap(m[i], m[s]);
dfs(m, s + 1, e);
swap(m[i], m[s]);
}
}
int main()
{
int m[10], n;
cin >> n;
for (int i = 0; i < n; i++) {
m[i] = i + 1;
}
dfs(m, 0, n - 1);
return 0;
}
测试(n = 7 时)
方法一:
方法二:
结论:
可以发现,方法二(交换法)的调用递归次数更少,时间复杂度更低,不过方法一得到的全排列结果是字典序的,而方法二(交换法)不是。
组合:
计算n个整数取m个的组合,求所有这些组合。
假设这n个整数是 1 ~ n
Input
两个整数 n 和 m 。 0 < n ≤ 20 , 0 < m ≤ 10
Output
输出a行,每行一个组合。
Sample Input
3 2
Sample Output
2 1
2 3
1 3
#include<stdio.h>
int a[12],k,n,m;
int book[22];
void dfs(int i)
{
if(i==m+1){
for(int b=1;b<=m;b++)
printf("%d ",a[b]);
puts("");
return;
}
for(int j=1;j<=n;j++){
if(!book[j]){
if(j>a[k]){ ///当前数要大于前一个数,关键一句,解决出现重复组合的情况
a[++k]=j;
book[j]=1;
dfs(i+1);
book[j]=0;
--k;
}
}
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
dfs(1);
return 0;
}