法一:使用next permutation
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
vector<char> seq;
string s;
cin>>s;
seq.assign(s.begin(),s.end());
sort(seq.begin(),seq.end());
do{
for(int i=0;i<seq.size();i++)
{
cout<<seq[i];
}
cout<<endl;
}while(next_permutation(seq.begin(),seq.end()));
return 0;
}
法二:使用简单DFS
在后面的代码中函数dfs的层数k代表着某一排列中的k个选择(一个排列中的第k个数字),具体机理类似下图(这个图也是理解递归的关键)
#include<iostream>
#include<vector>
#include<algorithm>
#include<string.h>
#include<stack>
#include<queue>
using namespace std;
int v[20]={0};//是否被访问
char res[20];
void dfs(int x,char *s,int n)
{
int i;
if(x==n+1)//dfs层数
{
for(i=0;i<n;i++) cout<<res[i];
cout<<endl;
}
else
for(i=0;i<n;i++)//递归思想理解
{
if(!v[i]){
v[i]=1;//表示访问过了
res[x-1]=s[i];
dfs(x+1,s,n);
v[i]=0;//每个排列之后对访问状态重置
}
}
}
int main()
{
string s0;
cin>>s0;
char s[20];
for(int i=0;i<s0.length();i++)
{
s[i]=s0[i];
}
sort(s,s+s0.length());//sort要到/0,表示s的尾部
dfs(1,s,s0.length());
return 0;
}
当然,该种方法使用了过多的堆栈,有更优化的方法。
另外一种dfs方法可以参照这篇博文
https://blog.csdn.net/qq_40742428/article/details/99436764
使用了回溯的方法
法三:使用字典序法
字典序法其实就是C++的nextpermutation的实现机理。
生成给定全排列的下一个排列:
所谓一个的下一个就是这一个与下一个之间没有其他的。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。
于是可以有下面计算下一个排列的算法:
1)简洁版
对于给定的一个数,首先从右边找到第一个相邻"逆序对",现假设下一个要找的数比这个数大,且中间没有一个数比前者大、比后者小。那么这个"逆序对"的定义是就是满足num[ i ]< num[ i+ 1 ](假设这个整数是以数组的形式存储的),然后再重新从右边起找出第一个比那个"逆序对"的较小者 要大的数,交换他们,再将那个较小数下标后面的子数组反转
2)严谨版
设P是1~n的一个全排列:p=p1p2…pn=p1p2…pj-1pjpj+1…pk-1pkpk+1…pn
1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi<pi+1}
2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)
3)对换pi,pk
4)再将pj+1…pk-1pkpk+1…pn倒转得到排列p’=p1p2…pj-1pjpn…pk+1pkpk-1…pj+1,这就是排列p的下一个排列。
代码实现
/**
* get the next permutation based on dictionary order method
*
* @param cur
* @return next permutation string, or null if cur is the last
*/
public static String next(String cur) {
String ret = null;
if (cur == null)
return ret;
int strlen = cur.length();
char[] lcur = cur.toLowerCase().toCharArray();
int j = strlen - 2;
while (j >= 0 && lcur[j] > lcur[j + 1]) {
j--;
}
if (j < 0)
return ret;
int k = strlen - 1;
while (lcur[k] < lcur[j]) {
k--;
}
// swap lcur[k], lcur[j]
char temp = lcur[k];
lcur[k] = lcur[j];
lcur[j] = temp;
// reverse lcur[j+1, ..., strlen-1]
int low = j + 1;
int high = strlen - 1;
while (low < high) {
temp = lcur[low];
lcur[low] = lcur[high];
lcur[high] = temp;
low++;
high--;
}
ret = String.valueOf(lcur);
return ret;
}
最后这一部分来自于摘录和转载。不断学习,共同进步。敬请期待。