生成非唯一(重复)排列

时间:2012-11-12 20:47:08

标签: c permutation combinatorics

我在C写了一个基本的排列程序。 用户键入一个数字,然后打印该数字的所有排列。

基本上,这是它的工作原理(主要算法是用于find the next higher permutation的算法):

int currentPerm = toAscending(num);
int lastPerm = toDescending(num);
int counter = 1;

printf("%d", currentPerm);

while (currentPerm != lastPerm)
{
   counter++;
   currentPerm = nextHigherPerm(currentPerm);
   printf("%d", currentPerm);
}

但是,当输入的数字包括重复的数字 - 重复时 - 一些排列不会被生成,因为它们是重复的。计数器显示的数字与预期的数字不同 - 它不显示数字中位数的阶乘,而是显示较小的数字,仅显示唯一的排列。

例如:

num = 1234567
counter = 5040 (!7 - all unique)

num = 1123456
counter = 2520

num = 1112345
counter = 840

我希望它能够将重复/重复的数字看作是不同的 - 我不想只生成唯一的排列 - 而是生成所有排列,无论是否重复和重复他人。

4 个答案:

答案 0 :(得分:1)

嗯......为什么不计算输入字符串长度的阶乘呢? ;)

答案 1 :(得分:1)

  

我希望它可以像处理那样处理重复/重复的数字   不同 - 我不想只计算唯一的数量   排列。

如果nextHigherPerm()使用的唯一信息是传入的数字,那么您就不走运了。考虑nextHigherPerm(122)。该函数如何知道它已经看到了多少版122nextHigherPerm(122)应该122还是212?除非你分别跟踪发电机的当前状态,否则无法知道。

答案 2 :(得分:1)

如果您有3个字母,例如ABC,您可以制作:ABC, ACB, BAC, BCA, CAB, CBA,6种组合(6!)。如果其中两个字母像AAB一样重复,你可以制作:AAB,ABA,BAA,它不是3!这是什么?它来自哪里?重复数字或字母时计算它的真正方法是使用组合 - > ( n k ) = n! / ( n! * ( n! - k! ) )

让我们做另一个说明性示例:AAAB,然后可能的组合只有AAAB, AABA, ABAA, BAAA四种组合,如果您按公式4C3 = 4.计算它们

生成所有这些列表的正确程序如何:

  • 将数字存储在数组中。示例ABCD
  • 将数组的0元素设置为pivot元素,并将其从temp数组中排除。 A {BCD}
  • 然后,如果您想要所有组合(甚至是重复的组合),请将时间数组的元素向右或向左移动(但您喜欢),直到到达n元素。
  

A {} BCD ------------ A {} CDB ------------ A {} DBC

  • 再次执行第二步,但使用临时数组。
  

A {B {CD}} ------------甲{C {DB}} ------------ A {d {BC}}

  • 再次执行第三步,但在第二个临时数组中。
  

A {B {CD}} ------------甲{C {DB}} ------------ A {d {BC}}

     

A {B {DC}} ------------甲{C {BD}} ------------ A {d {CB}}

  • 转到第一个数组并移动数组BCDA,将B设置为数据透视,然后执行此操作直到找到所有组合。

答案 3 :(得分:0)

为什么不将它转换为字符串然后将您的程序视为anagram生成器?