自己写的递归,几经修改终于AC
判断重复的语句很关键原来我的判断是如果之前的值与现在的一样且用过,则跳过,进行下一次循环
但这样会使之后的循环也跳过,导致不必要的查询,从而导致了超时。。
优化后是判断之后的值是否与现在的一样,如果没用过就把之后的值赋值给输出,这样就没问题了
#include <iostream>
#include <vector>
#include <string>
#include <math.h>
#include <iomanip>
#include <stdlib.h>
using namespace std;
char input[200],output[200];
int used[200];
int group=0;
int cmp(const void* a,const void* b)
{
return *(char*)a-*(char*)b;
}
void orderfun(int current,int length) //current代表当前打印第几个
{
for (int i=0;i<length;i++)
{
if (i<length-1&&input[i]==input[i+1]&&used[i+1]==0) //重复则运行下一个,判断下一个是否用过很关键,若判断上一个则超时了。。。会走很多弯路
continue;
if (used[i]==0)
{
output[current]=input[i];
used[i]=1;
if (current==length-1) //打印一种排列
{
printf("%s\n",output);
}
else
orderfun(current+1,length);
used[i]=0;
}
}
}
int main()
{
cin>>input;
int len=strlen(input);
qsort(input,len,sizeof(input[0]),cmp);
memset(used,0,sizeof(used));
orderfun(0,len);
}
这里还有一个用STL的方法做的很简单(STL类库太强大了。。。)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string str;
while(cin>>str)
{
sort(&str[0],&str[0]+str.length());//先排序
cout<<str<<endl;//输出排序后的
while(next_permutation(&str[0],&str[0]+str.length()))
{
cout<<str<<endl;
}
}
return 0;
}
下面有关next_permutation的介绍
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[10]={1,2,2,3,3,3,4,5,6,7};
int cnt=0;
do{
cnt++;
}while(next_permutation(a,a+10));
printf("%d\n",cnt);//输出302400
scanf("pause");
}
next_permutation的返回值如下:如果变换后序列是非减序的则返回0,否则返回1。
所以如果想用do{...}while(next_permutation(...));的方式生成一个集合的全排列,必须先做sort。
即 便做了sort,从上面的例子我们也可以看出,当集合存在重复元素时,循环的次数并不是10!=3628800,302400是什么呢,恰是10!/ (2!*3!),也就是这个多重集的全排列数。可见在处理有重复元素的"集合"时,它是正确的且高效的,只要记住一定要先sort