Java 有限重复排列算法

Java 有限重复排列算法,java,arrays,algorithm,math,permutation,Java,Arrays,Algorithm,Math,Permutation,是否有一种算法可以列出所有重复次数有限的排列?如果有一个现有的Java库,那就太好了 假设我们有3项{A,B,C}。我们想要两个项目的排列。它将是3P2: 但如果我们允许最多重复两次。会是什么样子?(我真的不知道。) 我试着想象一下,我们从集合{a,a,B,B,C,C}中得到一个2的排列。它将是6P2=30。但我们必须带走那些复制品。我手工做的,现在是9点。我不知道如何从数学计算9 {A, A} {A, B} {A, C} {B, B} {B, A} {B, C} {C, C} {C, A} {

是否有一种算法可以列出所有重复次数有限的排列?如果有一个现有的Java库,那就太好了

假设我们有3项
{A,B,C}
。我们想要两个项目的排列。它将是3P2:

但如果我们允许最多重复两次。会是什么样子?(我真的不知道。)

我试着想象一下,我们从集合
{a,a,B,B,C,C}
中得到一个2的排列。它将是6P2=30。但我们必须带走那些复制品。我手工做的,现在是9点。我不知道如何从数学计算9

{A, A}
{A, B}
{A, C}
{B, B}
{B, A}
{B, C}
{C, C}
{C, A}
{C, B}
(事实上,重复2的3P2不是一个好例子。这是因为排列中只有2个元素。因此,无限重复之间没有区别。重复2的4P3将是一个更好的例子。但很难列出所有排列。)

一个更好的示例:集合
{A,B,C,D}
的4P3:

{A, B, C}
{A, B, D}
{A, C, B}
{A, C, D}
{A, D, B}
{A, D, C}
... repeat for permutations starting from {B, ... }
... repeat for permutations starting from {C, ... }
... repeat for permutations starting from {D, ... }
以及重复限制为2的集合
{A,B,C,D}
的4P3:

{A, A, B}
{A, A, C}
{A, A, D}

{A, B, A}
{A, B, B}
{A, B, C}
{A, B, D}

{A, C, A}
{A, C, B}
{A, C, C}
{A, C, D}

{A, D, A}
{A, D, B}
{A, D, C}
{A, D, D}

... repeat for permutations starting from {B, ... }
... repeat for permutations starting from {C, ... }
... repeat for permutations starting from {D, ... }
是一个网页在谈论类似的事情。但它似乎需要nPn(选择所有元素)。此外,我还需要一个算法来生成和列出排列

谢谢你的帮助


对于编程实现,实际上有一种“不聪明”的方法


对于集合
{A,B,C,D}
,使用一个互补数组
int[0,0,0,0]
,它是每个元素的使用次数。每次选择元素时递增计数,并向前传递数组副本(沿调用树向下)。然后,受递归方法启发,对其进行修改以允许无限重复(不从元素集中删除所选的一个),并添加一个
if(used[i]在生成一个集合的所有可能分区之前,我遇到过这个问题。这基本上与您尝试做的是相同的概念。(给定大小的所有组合与该大小的分区的集合相同),我发现论文给出了一种非常快速的非递归算法来生成这些组合,而不重复任何C++实现。

< P>参见找到答案的理论公式。
论文信息是《组合理论杂志》Roberto Frucht的“有限重复的置换”,doi为10.1016/S0021-9800(66)80025-X

这有点晚了,但我在GitHub上有一个库可以做到这一点。以下是基本用法:

在项目中包含依赖项:

<dependency>
  <groupId>com.xiantrimble.combinatorics</groupId>
  <artifactId>combinatorics</artifactId>
  <version>0.2.0</version>
<dependency>

组合学
组合数学
0.2.0
然后通过从组合工厂获取虚拟集合来迭代排列:

import com.xiantrimble.combinatorics.CombinatoricFactory;
import com.xiantrimble.combinatorics.CombinatoricFactoryImpl;
import com.xiantrimble.combinatorics.Combinatoric;
...
int k = 6;
int[] domain = {1,1,1,1,2,2,2,3,3,4};
// create a factory.
CombinatoricFactory factory = new CombinatoricFactoryImpl();
Combinatoric<Integer> permutations = factory.createPermutations(k,  domain);

for( Integer[] permutation : permutations ) {
  System.out.println(Arrays.toString(permutation));
}
import com.xiantrimble.combinations.combinationFactory;
导入com.xintrimble.combinations.combinationicfactoryImpl;
导入com.xiantrimble.combinations.combinational;
...
int k=6;
int[]域={1,1,1,2,2,3,3,4};
//创建一个工厂。
CombinaticFactory=新的CombinaticFactoryImpl();
组合置换=工厂.createPermutations(k,域);
for(整数[]置换:置换){
System.out.println(array.toString(置换));
}

代码没有按字典顺序排列,而是为了尽量减少连续元素之间的变化,所以请记住这一点。此外,Sonatype的快照存储库中提供的0.3.0-SNAPSHOT版本也有一些改进。

不会生成
{a,B,C}
(任意长度)允许每个元素的单个重复与生成相同长度的
{a,a,B,B,C}
的排列相同?对于长度=3,如果
{a,a,B,B,C,C}
的元素是不同的,即
a!=a
,它将是P(6,3),并且具有重复的
{a,a,B}
{a,a,B}
,这是不需要的。从技术上讲,一个集合不允许repetition@ricard.m.o.,嗯…你的意思是nPr/排列不能处理重复的元素吗?如果是这样,我们可能不得不从另一个角度考虑。排列是一种特殊的有序序列,元素只出现一次。如果链接变成不可用,请不要发布仅链接的答案不可用,则此答案没有任何价值。请尝试将主要观点纳入您的答案。请不要发布仅链接的答案,如果链接不可用,则此答案没有任何价值。尝试将主要观点纳入您的答案。
import com.xiantrimble.combinatorics.CombinatoricFactory;
import com.xiantrimble.combinatorics.CombinatoricFactoryImpl;
import com.xiantrimble.combinatorics.Combinatoric;
...
int k = 6;
int[] domain = {1,1,1,1,2,2,2,3,3,4};
// create a factory.
CombinatoricFactory factory = new CombinatoricFactoryImpl();
Combinatoric<Integer> permutations = factory.createPermutations(k,  domain);

for( Integer[] permutation : permutations ) {
  System.out.println(Arrays.toString(permutation));
}