因为每次都进行的是将数组中的数与第一个数进行交换,它注重的是所有的全排列,但没有注意到换位顺序的问题,这样会产生一个问题:比如 1 2 3 4 的全排列,处理2,3,4的全排列时会将4与2交换,这样会出现1432排在1423的前面。所以如果对全排列的顺序有非常严格的顺序,就不能用perm算法。
例如,abc的全排列:
有序全排: perm全排:
abc abc
acb acb
bac bac
bca bca
cab cba
cba cab
接下来,我们来看一看perm算法的另一大问题,如果对有重复元素的序列进行全排呢?例如:输入122则会输出什么呢?很遗憾,输出结果为:122,122,212,221,221,212(如果你能直接说出来,那么你对perm算法的运行流程就弄明白了),这样的结果明显是不对的,该如何解决呢?我们来看一下,第1个数与第2个数交换得到212(此时第一个数在第二个位置),接着第3个数与第2个数交换得到221(此时第一个数1在第三个位置上,第三个数在第二个位置上,第二个数在第一个位置上),然而第二个数与第三个数是相等的(原序列上),这不相当于直接第三个数与第一个数交换了吗?一下子把下面的事给做了。所以第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数就行了…
代码:
#include<CSTDIO>
#include<CSTRING>
#define MAX 10
using namespace std;
void swap(char str[],int i,int j)
{
int temp;
temp=str[i];
str[i]=str[j];
str[j]=temp;
}
bool IsUnique(char str[],int start,int end)//检查重复项
{
int i;
for(i=start;i<END;I++) if(k i; int { m) k,int str[],int perm(char void } true; return false; if(str[i]="=str[end])">m)
{
for(i=0;i<=m;i++)
printf("%c",str[i]);
printf("\n");
}
else
{
for(i=k;i<=m;i++)
{
if(IsUnique(str,k,i))
{
swap(str,k,i);
perm(str,k+1,m);
swap(str,k,i);
}
}
}
}
int main(int argc,char *argv[])
{
char str[MAX];
while(scanf("%s",str)!=EOF)
{
int len=strlen(str);
perm(str,0,len-1);
printf("\n");
}
return 0;
}