如何确定两个有序集之间的排列符号?

时间:2014-04-21 15:59:16

标签: algorithm permutation

假设A和B是两个大小相同但每个都没有重复成员的数组。

是否有任何有效的算法?

1.确定A和B是否具有相同的成员

2.如果1的答案为真,则决定将A带到B的排列的符号(f(A [i])== f(B [i]))?

谢谢。

3 个答案:

答案 0 :(得分:2)

您可以使用哈希表找到将A转换为B的排列:

pos = hash table (value -> position) of B
perm = []
for a in A:
    if a not in pos: return "not the same!"
    perm += [pos[a]]

此部分需要O(n)预期时间。

现在你必须找到排列的标志。您至少有两个选择:

实际上,您可以直接在输入数组上使用循环分解,这将产生一个很好的简短实现。

答案 1 :(得分:0)

一个有效的算法(O(n ^ 2))将如下(假设两个数组中都没有重复)。

bool same;
for(int i=0; i<L; i++)
{
    same = false;
    for(int j=0; j<L; j++) // see if A[i] is in B
       if(A[i]==B[j]) 
       {
           same = true; // found A[i] in B
           break;
       }
    if(!same) // A[i] was not found in B 
       break;
}

这里L是数组的长度。在循环结束时,如果数组包含相同的元素,same将为true,否则为false。希望这可以帮助。

PS:如果数组包含重复项,则此代码会告诉您A是否包含B。但是,您可以互换AB的角色,并决定B中是否包含A。如果AB中包含B AA=B,则{{1}}。

答案 2 :(得分:0)

这是一个通用的算法问题,还是您要求特定的(基于语言的)实现?

对于问题#1,只需在O(nlog(n))中对每个数组进行排序,然后比较O(n)中的数组。

如果输入值的范围不是很大,那么您可以使用直接哈希表并在O(n)中执行排序阶段,从而将整体复杂度从O(nlog(n))降低到{{1 }}

在Java中,您可以使用O(n)实例来实现此目的。我不确定这个类的内部实现,但它可以为大范围的输入值实现相同的性能甚至


对于问题#2,由于没有重复元素,所以排列总数为HashMap

您可以计算整个排列组中每个数组的排列ID,然后使用您计算的ID对来唯一地标识两个数组之间的映射。

例如,假设n!A = {3,2,1,4}

排列总数为24,因此每个排列都可以映射到0到23之间的ID:

B = {4,1,3,2}
  • 数组1,2,3,4 ==> 0 1,2,4,3 ==> 1 1,3,2,4 ==> 2 1,3,4,2 ==> 3 1,4,2,3 ==> 4 1,4,3,2 ==> 5 2,1,3,4 ==> 6 2,1,4,3 ==> 7 2,3,1,4 ==> 8 2,3,4,1 ==> 9 2,4,1,3 ==> 10 2,4,3,1 ==> 11 3,1,2,4 ==> 12 3,1,4,2 ==> 13 3,2,1,4 ==> 14 3,2,4,1 ==> 15 3,4,1,2 ==> 16 3,4,2,1 ==> 17 4,1,2,3 ==> 18 4,1,3,2 ==> 19 4,2,1,3 ==> 20 4,2,3,1 ==> 21 4,3,1,2 ==> 22 4,3,2,1 ==> 23 已映射到ID 14
  • 数组A已映射到ID 19
  • 映射f(A,B)=(14,19)

如果您希望此函数产生单个值,则可以使用B代替n!*id1+id2


或者,您可以定义映射函数f(A,B)以返回索引更改数组。

例如,假设id1,id2A = {3,2,1,4}

  • 索引0处的元素移动到索引2,因此索引更改为+2
  • 索引1处的元素移动到索引3,因此索引更改为+2
  • 索引2处的元素移动到索引1,因此索引更改为-1
  • 索引3处的元素移动到索引0,因此索引更改为-3

因此,B = {4,1,3,2}应返回数组f({3,2,1,4},{4,1,3,2})