问题描述:
给定一个字符串"abc",输出由字符'a','b','c'所能排列出来的所有字符串abc,acb,bac,bca,cab,cba
解法一 递归实现
依次将a,b,c固定在第一位,然后求后面两个数的排列
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
void CalcAllPermutation(char *perm,int from,int to){
if(to < 0)
return;
if(from == to){
for(int i=0;i<=to;i++)
cout<<perm[i];
cout<<endl;
}
else{
for(int j=from;j<=to;j++){
swap(perm[j],perm[from]);
CalcAllPermutation(perm, from+1, to);
swap(perm[from],perm[j]);
}
}
}
int main(){
char perm[10];
cin>>perm;
CalcAllPermutation(perm,0,strlen(perm)-1);
return 0;
}
解法二 字典序排列
大致意思是,我们可以以字典的顺序求出紧接着这个序列的下一个序列。
比如,12345 的下一个序列是 12354 , 下一个是 12435 下一个是 12453…… 最后一个是 54321
关键就是如何一个接一个地求出下一个序列。
方法:
1.先从右到左看,确定第i个元素,这个元素的特征是这样的:它是第一个满足其右边有元素大于它的。
2.将大于它的元素和第i个元素置换
3.最后将第i个元素之后的元素来一次翻转
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
bool CalcAllPermutation(char *perm,int num){
int i;
for(i=num-2; (i>=0)&& perm[i]>perm[i+1] ;i--);
if(i < 0)
return false;
int k;
for(k=num-1; (k>i)&& perm[k]<=perm[i];k--);
swap(perm[i],perm[k]);
reverse(perm+i+1,perm+num);
return true;
}
int main(){
char perm[10];
cin>>perm;
int length = strlen(perm);
int count = 1;
for(int i=1;i<=length;i++)
count = count * i;
int sum = 1;
for(int i=0;i<length;i++)
cout<<perm[i];
cout<<endl;
while(sum < count){
if(CalcAllPermutation(perm,length)){
for(int i=0;i<length;i++)
cout<<perm[i];
cout<<endl;
sum ++;
}
}
return 0;
}