给定一串字典序不递减的字符串,可能含有相同元素。请借助递归设计算法求出该字符串的所有不同排列。请不要借助STL。
输入格式:
第一行输入一个整数T(小于等于10),代表有T组测试样例。
接下来T行,每行给定一串字符串(长度小于等于9,且至少有3个字符相同)。
输出格式:
每行输出一个字符串。按照字典序递增的顺序输出,每个排列占一行。
最后一行输出不同排列的个数。
提示:
大量输出,请用printf代替cout,否则会超时。
样例输入:
1
aacc
样例输出:
aacc
acac
acca
caac
caca
ccaa
6
解题思路:
这是一道典型的全排列问题,但是要求字典排序输出,所以这又是一道特殊的全排列问题。代码基本和全排列相同,只需要改动全排列交换的顺序的部分就可以了。全排列问题的讲解如下(递归解决全排列问题)
代码如下:
#include <iostream>
#include <string.h>
using namespace std;
int all;
int isequal(char list[],int k,int i)
{
if(i>k)
{
for(int j=k;j<i;j++) //检测i前面的字符,如果有和i相等的就不再排i了
if(list[j]==list[i]) //由于这串字符串是顺序排列的,也可以直接比较i和i前面一个的字符是否相等
return 0;
}
return 1;
}
void swap1(char list[],int k,int i) //递归初始交换(与全排列不同之处)
{
char m=list[i];
for(int j=i;j>k;j--)
{
list[j]=list[j-1];
}
list[k]=m;
}
void swap2(char list[],int k,int i) //递归结束还原(与全排列不同之处)
{
char m=list[k];
for(int j=k;j<i;j++)
{
list[j]=list[j+1];
}
list[i]=m;
}
void perm(char list[],int k,int m)
{
//产生list[k:m]的全排列
if(k==m)
{
//只剩下一个元素
all++;
printf("%s\n",list);
}
else //还有多个元素带排列,递归产生排列
{
for(int i=k;i<=m;i++)
{
if(isequal(list,k,i))
{
swap1(list,k,i);
perm(list,k+1,m);
swap2(list,k,i);
}
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
all=0;
char list[9];
cin>>list;
int p=strlen(list);
perm(list,0,p-1);
printf("%d\n",all);
}
return 0;
}