我想要做的是创建一个算法,能够找到两组对象之间的所有可能的双射。
一个简单的例子,假设我们有两个数组{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 \
尽管起初看起来很简单,但我很困惑。在组合学,双射或排列理论中是否有任何标准算法来解决这个问题? 先感谢您。
克里斯蒂娜
答案 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)]