一、初识全排列
在对n个元素且含有重复进行全排列时,其全排列的种类数量不在是n!种,因为含有重复元素,故对其进行全排列中含有重复的全排列类型。故在处理含有重复元素的问题时,需要对这些重复的元素进行相应的处理,即在进行全排列中需要对相应的重复元素进行去重。
二、相应的算法
1.交换法
代码如下(示例):
#include <bits/stdc++.h>
using namespace std;
int number=0;
void f(int p,string str,int n){
if(p==n){
cout<<str<<endl;
number++;
return;
}
sort(str.begin()+p,str.end()); //使字符串按照升序进行排列
for(int i=p;i<n;i++){
if(i>p&&str[i]==str[i-1]){ //未进行相关交换前进行去重,在此去重时原始的字符串必须是有序的。
continue;
}
swap(str[i],str[p]);
f(p+1,str,n);
swap(str[i],str[p]);
}
}
int main(){
string str="aabb";
f(0,str,str.length());
cout<<number<<endl;
return 0;
}
2.抽取法
代码如下(示例):
#include <bits/stdc++.h>
using namespace std;
int number=0;
int vis[15]={0}; //表示未被访问过
void f(string a,int n,char b[],int p){
if(p==n){
cout<<b<<endl;
number++;
return;
}
//在对字符串进行有序排列中,也可以开始就对他进行有序排列,因为在每次进行追加中其vis[i]均会被置为0,回到其初始状态
for(int i=0;i<n;i++){
// sort(a.begin()+i,a.end());
if(i>0&&a[i]==a[i-1]&&!vis[i-1]){//进行去重,在去重需要是原来的字符串有序,同时保证a[i-1]未被访问过
continue;
}
if(!vis[i]){
b[p]=a[i];
vis[i]=1;
f(a,n,b,p+1);
vis[i]=0;
}
}
}
int main(){
string str="baba";
sort(str.begin(),str.end()); //对字符串进行有序排列
char b[15]="";
f(str,str.length(),b,0);
cout<<number<<endl;
return 0;
}
3.使用next_permutataion进行全排列
代码如下(示例):
#include <bits/stdc++.h>
using namespace std;
int main(){
string str="baba";
sort(str.begin(),str.end());
int number=0;
do{
cout<<str<<endl;
number++;
}while(next_permutation(str.begin(),str.end()));
cout<<number<<endl;
return 0;
}