问题 A: 【递归入门】全排列
时间限制: 1 Sec 内存限制: 128 MB
提交: 1032 解决: 645
[提交][状态][讨论版][命题人:外部导入]
题目描述
排列与组合是常用的数学方法。
先给一个正整数 ( 1 < = n < = 10 )
例如n=3,所有组合,并且按字典序输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
输入
输入一个整数n( 1<=n<=10)
输出
输出所有全排列
每个全排列一行,相邻两个数用空格隔开(最后一个数后面没有空格)
样例输入
3
样例输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
C++版
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=100010;
int a[maxn];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
a[i]=i+1;
}
do{
for(int i=0;i<n;i++){
if(i) cout<<" ";
cout<<a[i];
}
cout<<endl;
}while(next_permutation(a,a+n));
return 0;
}
递归版
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=100010;
int n;
int a[maxn];
vector<int> ans;//用来存放结果
bool hashTable[maxn]={false};
//数被选中,则标记为true,未被选中标记为false
void dfs(){
if(ans.size()==n){//当n个数据都处理完时,即得到一个全排列,开始按要求输出
for(int i=0;i<ans.size();i++){
if(i) cout<<" ";
cout<<ans[i];
}
cout<<endl;
return ;//此时一个子排列已经输出,此次递归已到头,相当于进入了死胡同,开始返回
} //先返回到最近的一个分岔口 1 2 3 -->1 * *
for(int i=0;i<n;i++){
if(hashTable[a[i]]==false){//如果这个数未被使用
hashTable[a[i]]=true;
ans.push_back(a[i]);
dfs();//dfs返回到此层时即第i位可以选择其他数了,所以后续步骤要弹出第i位的数
ans.pop_back();//弹出后表示该位置的这个数还能再用于其他位置
hashTable[a[i]]=false;
}
}
}//此种方法是每个数只能选一次 刚好符合题意 全排列
//第i位选a[i] 然后标记该数hashTable[a[i]]=true,表示当前序列已经
//选过该数
int main(){
cin>>n;
for(int i=0;i<n;i++)
a[i]=i+1;
dfs();
return 0;
}