全排列思想
1.先进行字典序的排序。
2.按照字典序从打到小依次递归
1-n的排列
方法分析
开头是1,后面是2-9的全排列
开头是2,后面是1和3-9的全排列
以此类推,前x项排号,后n - x项全排列
依旧是递归
函数代码
void print_permutation(int n, int *A, int cur)
{
if (cur == n)
{
for (int i = 0; i < n; i++)
printf("%d ", A[i]); // 当cur == n时,所有的数字递归完毕 输出
printf("\n");
}
else
{
for (int i = 1; i <= n; i++)
{ //在这里假设将i放入cur位置 下文判重
int ok = 1;
for (int j = 0; j < cur; j++)
{
if (A[j] == i)
ok = 0;
}
if (ok == 1)// 如果ok = 1 那么没有重复
{
A[cur] = i;// 将i放入出入位置
print_permutation(n, A, cur + 1); //递归
}
}
}
}
有重集的排列
分析
1.将代码中对i的判断改为对p[i]的判断
2.为了防止重复字符干扰到判重的过程 我们c1,c2来分别标记 重复字数在j和p的出现次数
3.遇到相邻的两个元素相同的时候为了排除相同的重复情况
在第二个for循环下加入 if(!i || p[i] != p[i - 1])
代码
void print_permutation(int n, int *A, int * p, int cur)
{
if (cur == n)
{
for (int i = 0; i < n; i++)
printf("%d ", A[i]);
printf("\n");
}
else
{
int c1 = 0, c2 = 0;
for (int i = 0; i < n; i++)// 此处为n个数字中有m个数字的全排列(n - m 为重复的个数)
if (!i || p[i] != p[i - 1])// 此处IF是为了排除当初始序列P中含有多个相同的数值时重复计算
{ // 当然此处的前提是n个数字是完全排好序的 sort
for (int j = 0; j < cur; j++)
if (A[j] == p[i])
c1++;
for (int j = 0; j < n; j++) // 此处上下c1, c2 代表的是在数列 a和p中某一个数字出现的次数 (主要是用来针对数列中存在重复数字的问题)
if (p[i] == p[j])
c2++;
if (c1 < c2)// 如果C1小于c2 那么代表在p中还有可以供a调用的重复数字
{
A[cur] = p[i];// 赋值 下一步
print_permutation(n, A, p, cur + 1);
}
}
}
}
C++函数全排
首先要升序快排
sore(a, a + n);
附降序方法:
bool compare (int a, int b)
{
return a > b;
}
sore(a, a + n, compare);
第二步调用函数next_permutation
例子: next_permutation(a, a + n);