全排列
一般的情况都是给出n个数,求出其不同顺序的排列方式;
全排列的实现
1.字典序法
根据全排列的公式,f(n)=n!
不难推断出可以用DFS来求其所有不同的排列顺序;这种方法得出的顺序符号字典序排列。
这是它的生成树
代码实现
void DFS(int x){
if(x>=n){
for(int i=0;i<n;i++){
cout<<" "<<num[i];
}
cout<<endl;
return;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
vis[i]=1;
num[x]=i;
DFS(x+1);
vis[i]=0;
}
}
}
2.递归求法
全排列的核心思想就是交换,即全排列是从第一个元素开始,每个元素都和它后面的元素进行位置的互换从而得到。
;
#include<bits/stdc++.h>
using namespace std;
/*
思路:
1 2 3
*/
int n;
int num[100];
int ans;
void swap(int a,int b){
int temp=num[a];
num[a]=num[b];
num[b]=temp;
}
void fullpermutation(int k){
if(k==n){
ans+=1;
for(int i=1;i<=n;i++)
cout<<num[i]<<" ";
cout<<endl;
return;
}
for(int i=k;i<=n;i++){
swap(i,k);
fullpermutation(k+1);
swap(i,k);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)num[i]=i;
fullpermutation(1);
cout<<ans<<endl;
return 0;
}
全排列的去重
上述解法是在序列中的数不重复的情况下才能使用;对于序列元素不唯一的情况,则应用以下解法;
1.判断num[k]与num[i]之间是否存在与num[i-1]相等的值,如果存在,就不进行交换;
2.解释:
a.取序列{1,2,3,1}
b.因为递归的执行顺序是从外层递进到最里层,再依次返回;
c.~~~原因我还不是很了解,待更新~~~
3.我是参考的这篇文档,但还是有点疑惑
https://www.cnblogs.com/xiezhw3/p/3448270.html
代码实现
#include<bits/stdc++.h>
using namespace std;
/*
思路:
1 2 3
*/
int n;
int num[100];
int ans;
void swap(int a,int b){
int temp=num[a];
num[a]=num[b];
num[b]=temp;
}
bool Judge(int s,int e){
for(int i=s;i<e;i++){
if(num[s]==num[e])return false;
}
return true;
}
void fullpermutation(int k){
if(k==n){
ans+=1;
for(int i=1;i<=n;i++)
cout<<num[i]<<" ";
cout<<endl;
return;
}
for(int i=k;i<=n;i++){
if(Judge(k,i)){
swap(i,k);
fullpermutation(k+1);
swap(i,k);
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>num[i];
fullpermutation(1);
cout<<ans<<endl;
return 0;
}
全排列函数
do{
for(int i=0;i<n;i++)
cout<<num[i]<<" ";
cout<<endl;
}while(next_permutation(num,num+n));
这个pernutation函数需要注意的一点是其结果是按'字典序+去重'输出的;
但是,有一个坑点,那就是结果是从当前字典序位置开始,直到最大字典序位置!