题目:
输入一个字符串,打印出该字符串中字符的所有全排列》例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc.、acb、bac。cab和cba。
一、递归版本
1、未去除重复值
子问题:第一个数字与后面每一个数字进行交换
结束条件:遍历到最后一个字符,后面再也无法进行交换
代码如下:
void FullPermutation(char arr[], int length)
{
void Process1(char arr[], int index, int length);
if (arr == NULL || length <= 0)
return;
Process1(arr, 0, length);
}
void Process1(char arr[],int index, int length)
{
if (index == length - 1)
{
static int count1 = 1;
cout << "第" << count1++ << "全排列是:" << arr << endl;
}
for (int i = index; i < length; ++i)
{
std::swap(arr[index], arr[i]);
Process1(arr, index + 1, length);
std::swap(arr[index], arr[i]);
}
}
测试用列:
void Test1()
{
char arr[] = "123";
FullPermutation(arr, strlen(arr));
}
运行结果如下:
2、去除重复值
上述代码有一个小问题,但输入重复数字的时候,将会出现重复的全排列
例如输入122,上述代码运行结果如下:
解决方法:
先判断两个字符间的有无相同的字符,假如没有则进行交换,有相同的则不进行交换(因为实际是是全排列过程是从后往前排的)
代码如下:
void FullPermutation(char arr[], int length)
{
void Process1(char arr[], int index, int length);
if (arr == NULL || length <= 0)
{
return;
}
Process1(arr, 0, length);
}
void Process1(char arr[],int index,int length)
{
bool IsSwap(char arr[], int left, int right);
if (index == length - 1)
{
static int count = 1;
cout << "第" << count << "次全排列为:" << arr << endl;
return;
}
for (int i = index; i < length; ++i)
{
if (IsSwap(arr, index, i))//<span style="color:#ff0000;">增加一个比较的函数,判断是否应该发生交换</span>
{
std::swap(arr[i], arr[index]);
Process1(arr, index + 1, length);
std::swap(arr[i], arr[index]);
}
}
}
bool IsSwap(char arr[], int left, int right)
{
for (int i = left; i < right; ++i)
{
if (arr[i] == arr[right])
{
return false;
}
}
return true;
}
二、非递归版本