全排列算法是程序员应该掌握的基本算法之一,STL库中也有相应的函数。与排序算法类似,虽然STL库中提供了相应功能的函数,但我们应该掌握它的思想与实现。
- 思路
example: 求 "aabb"的全排列
'a'开头 + "abb"的全排列
'b'开头 + "aab"的全排列
这样 "aabb"的全排列转化为求 "abb","aab" 的全排列。
以此类推,不断将大规模的全排列问题转化为小规模的问题。
该思想是用递归实现的,代码如下:
void permutationCore(string str, int i, int len, vector<string> &ret){
if(i==len){
ret.push_back(str);
return;
}
else{
map<char,int>record; //保存已经出现过的字符,避免出现重复
for(int j=i; j<len; ++j){
// record[str[j]]==0 表示str[j]是第一次出现
if(record[str[j]]++==0){
swap(str[i],str[j]); //把str[j]放置到开头
// 求 str[i+1] 到str[len-1]的全排列
permutationCore(str,i+1,len,ret);
}
}
}
}
vector<string> Permutation(string str) {
if(str.empty()) return {};
vector<string> ret;
permutationCore(str,0,str.size(),ret);
return ret;
}
- STL库 next_permutation()实现
next_permutation() 说明
- 和其他泛型函数一样,在头文件 #include< algorithm > 中,参数是两个迭代器
- 在按字典序排序的全排列中,如果当前排列的下一个排列存在,返回true,并且变成下一个排列。 如果当前排列是全排列的最后一个排列,则返回false.
代码如下:
vector<string> Permutation(string str) {
if(str.empty()) return {};
vector<string> ret;
sort(str.begin(),str.end());
ret.push_back(str);
//str的下个排列存在,str变成下一个排列,返回true,反之返回false
while(next_permutation(str.begin(),str.end())){
ret.push_back(str);
}
return ret;
}