查找两组之间的所有可能的双射

时间:2012-02-11 19:10:09

标签: arrays algorithm math permutation

我想要做的是创建一个算法,能够找到两组对象之间的所有可能的双射。

一个简单的例子,假设我们有两个数组{1,2,3} {4,5,6}。

该算法应该给我3!= 3 * 2 * 1 = 6次以下的投射:

1-4 2-5 3-6 \ 1-4 2-6 3-5 1-5 2-4 3-6 \ 1-5 2-6 3-4 1-6 2-5 3-4 1-6 2-4 3-5 \

尽管起初看起来很简单,但我很困惑。在组合学,双射或排列理论中是否有任何标准算法来解决这个问题? 先感谢您。

克里斯蒂娜

3 个答案:

答案 0 :(得分:2)

你应该递归地,“选择”每个变量中的一个 - 并将其添加到解决方案中 - 为所有可能性做到这一点,并在每次递归调用时缩小可能的选择。

伪代码应该是[假设| S1 | == | S2 |]:

getAllBijections(S1,S2,sol):
   if (S1 is empty):
       print sol
   else:
       first <- S1.first
       S1 <- S1.deleteFirst()
       for each e in S2:
           S2.remove(e)
           sol.append(first,e)
           getAllBijections(S1,S2,sol) // note we are invoking with modified S1,S2,sol
           sol.removeLast() //remove the last sol
           S2.add(e) //return e to S2
       end for
   end if

请注意,确实会生成n!种可能性,因为对于每次迭代,您可以选择少一个元素,从而产生n * (n-1) * ... * 1 = n!种可能性,如预期的那样。

答案 1 :(得分:2)

  

组合学,双射或排列理论中是否有任何标准算法可以解决这个问题?

是!生成两组N个元素之间的所有双射与生成N个元素的所有排列相同;将排列视为指示,对于第一组的每个元素,第二组中的哪个元素将是双射下的图像。因此,您正在寻找一种算法来生成所有排列&#34;。

Knuth在这个主题上有一个简短的book,你也可以免费下载:&#34; The Art of Computer Programming: Generating all Permutations&#34; (注意:压缩的postscript格式)。他给出的第一个算法是&#34;算法L&#34;,这是一个有趣的替代明显的递归算法。

维基百科对&#34; Algorithms to generate permutations&#34;的讨论你会感兴趣的。如果您使用C ++编程,则可以使用next_permutation函数中的实现。

(当然,这假设你在讨论可数集,而不是像x ⟼ x+1这样的实数的双射。)

答案 2 :(得分:2)

简化此问题的一种方法是简单地获取第二个数组的所有排列,然后在第一个数组和每个置换的第二个数组之间执行n对n映射。

例如,如果你有[1,2]和[3,4],首先计算[3,4] - &gt;的排列。 {[3,4],[4,3]},然后将每个配对[1,2]。结果是{[(1,3),(2,4)],[(1,4),(2,3)]}。

我在Python中包含了一个示例实现,如下所示。

import itertools
a = [1,2]
b = [3,4]

for p in itertools.permutations(b):
    print zip(a,p)

# Output:
# [(1, 3), (2, 4)]
# [(1, 4), (2, 3)]