字符串的全排列
给定字符串S[0…N-1],设计算法,枚举S的全排列。
如果字符没有重复
递归算法
以字符串1234为例:
1 – 234
2 – 134
3 – 214
4 – 231
如何保证不遗漏: 保证递归前1234的顺序不变。
递归Code:
char str[]="1234";
int size =sizeof(str)/sizeof(char);//size为5,因为字符串最后以‘0’结尾
void Permutation(int from,int to)
{
if(from==to)
{
for(int i=0;i<=to;i++)
{
cout<<str[i];
}
cout<<'\n';
return;
}
for(int i=from;i<=to;i++)
{
swap(str[i],str[from]);//交换,以某个字符打头。比如:将2打头, 变为 2134
Permutation(from+1;to);
swap(str[i],str[from]);//还原成1234,从而保证递归前1234的顺序不变。
}
}
int main()
{
Permutation(0,size-2);//从第0个,到第3个。
return 0;
}
如果字符有重复
去除重复字符的递归算法
以字符1223为例:
1 – 223
2 – 123
3 – 221
带重复字符的全排列就是每个字符分别与它后面非重复出现的字符交换。
即:第i个字符与第j个字符交换时,要求[i,j)中没有与第j个字符相等的数。
IsSwap(int from,int to)是为了判断是否可以交换,如果是重复字符,就不需要交换了。
IsSwap(int from,int to)函数的时间复杂度为n,就出现了上面的n^2。所以有空间来换取时间。
利用mark[]数组,来标记重复数字是否已经使用过。