问题一:题意:输入一个整数n(n <= 9),输出1、2、3、······、n这n个数的全排列(按照字典序输出)。
方法1:暴力写法
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 int main(){
5 int n=3, a[20];//以n=3为例,以此类推
6 for(int i=0; i<n; i++)a[i]=i+1;//初始化序列
7
8 for(int i=0; i<n; i++)
9 for(int j=0; j<n; j++)
10 if(i!=j)
11 for(int k=0; k<n; k++)
12 if(k!=i && k!=j)
13 //....//当n不等于3时以此类推
14 cout<<a[i]<<" "<<a[j]<<" "<<a[k]<<endl;
15 return 0;
16 }
方法2:搜索写法
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n, m;
4 int a[100];
5 bool vis[100];
6 void dfs(int x)
7 {
8 if(x>n){
9 for(int i=1; i<=n; i++)cout<<a[i]<<" ";
10 cout<<endl;
11 return;
12 }
13 for(int i=1; i<=n; i++)
14 {
15 if(!vis[i])
16 {
17 a[x]=i;
18 vis[i]=1;
19 dfs(x+1);
20 vis[i]=0;
21 }
22 }
23
24 }
25 int main()
26 {
27 cin>>n;
28 dfs(1);
29 return 0;
30 }
方法3:递归写法
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n, a[10];
4
5 void perm(int begin, int end){
6 if(begin==end){
7 for(int i=0; i<=end; i++)
8 cout<<a[i]<<" ";
9 cout<<endl;
10 }
11 else{
12 for(int i=begin; i<=end; i++){
13 swap(a[begin],a[i]);//把当前第一个数与后面的所有数交换位置
14 perm(begin+1,end);
15 swap(a[begin],a[i]);//恢复,用于下次交换
16 }
17 }
18 }
19
20 int main(){
21 cin>>n;
22 for(int i=0; i<n; i++)a[i]=i+1;//初始化数组值
23
24 perm(0,n-1);//perm是permutation简写
25 return 0;
26 }
方法4:STL输出全排列
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 int main(){
5 int n, a[20];
6 cin>>n;//n小于20
7 for(int i=0; i<n; i++)a[i]=i+1;
8 do{
9 for(int i=0; i<n; i++)
10 cout<<a[i]<<" ";
11 cout<<endl;
12 }while(next_permutation(a,a+n));//next_permutation注意拼写要牢记
13
14 return 0;
15 }
问题二:打印n个数中任意m个数的全排列;
将问题一中方法2、方法3、方法4更改参数即可
问题三:
从1-m中选出n个数,要求同样的数字不能重复选择,按照字典序正序输出所有方案。
例如:从1到4中选出2个数,共有6种方法,按照字典序输出,依次为:
1 2
1 3
1 4
2 3
2 4
3 4
方法1:更改问题一》方法2》两种更改方法》自行脑补
方法2:递归写法,理解了你就是大佬
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n, m;
4 int a[20];
5 void dfs(int cur, int sel){//cur填数,sel位数
6 if(sel==n){
7 for(int i=0; i<n; i++)
8 cout<<a[i]<<" ";
9 cout<<endl;
10 return;
11 }
12 for(int i=cur; i<=m; i++){
13 a[sel]=i;
14 dfs(i+1,sel+1);
15 }
16 }
17 int main()
18 {
19 cin>>m>>n;
20 dfs(1,0);
21
22 return 0;
23 }
问题四:打印n个数中任意m个数的组合(子集问题)
step1:1~n的所有子集(难度较大,从二进制的角度考虑)
1 #include<bits/stdc++.h>
2 using namespace std;
3 int a[10];
4 void print_subset(int n)
5 {
6 for(int i=0; i<(1<<n); i++){
7 for(int j=0; j<n; j++)
8 if(i&(1<<j))
9 cout<<a[j]<<" ";
10 cout<<endl;
11 }
12 }
13 int main()
14 {
15 int n;
16 cin>>n;
17 for(int i=0; i<n; i++)a[i]=i+1;//初始化数组
18 print_subset(n);
19 return 0;
20 }
step2:打印1~n个数中任意m个数的组合(和问题二的解法比较)
1 #include<bits/stdc++.h>
2 using namespace std;
3 int a[10];
4 void print_subset(int n, int m)
5 {
6 for(int i=0; i<(1<<n); i++){
7 int num=0, kk=i;//num统计i中1的个数;kk用来处理i
8 while(kk){
9 kk=kk&(kk-1);//清除kk中的最后一个1
10 num++;//统计1的个数
11 }
12 if(num==m){//二进制数中的1有k个,符合条件
13 for(int j=0; j<n; j++)
14 if(i&(1<<j))
15 cout<<a[j]<<" ";
16 cout<<endl;
17 }
18 }
19 }
20 int main()
21 {
22 int n, m;
23 cin>>n>>m;
24 for(int i=0; i<n; i++)a[i]=i+1;//初始化数组
25 print_subset(n, m);
26 return 0;
27 }