不重复的随机配对

时间:2010-06-15 15:12:19

标签: algorithm data-structures

对我来说这个小项目/问题来自左侧领域。希望有人可以帮助我。我有一些粗略的想法,但我确信(或者至少我希望)存在一个简单,相当有效的解决方案。

提前致谢....伪代码很好。我通常使用.NET / C#,如果能够解决你的解决方案。

假设:

将定期召开会议的n个人群。我需要形成以前没有见过的对。随着时间的推移,人才库会慢慢变化。出于配对的目的,(A& B)和(B& A)构成相同的对。保持先前配对的历史。出于问题的目的,假设偶数个人。对于每次会议(对的集合),个人只会配对一次。

是否有一种算法可以让我们形成这些对?理想情况下,比以随机顺序排序对,生成配对然后检查先前配对的历史更好。一般来说,配对中的随机性都可以。

再多一点:

我可以通过多种方式创建一个随机化的池,从中可以拉出一对个体。根据历史记录检查这些内容,然后将它们放回池中或删除它们并将它们添加到配对个人列表中。我无法理解的是,在某些时候,我会留下一些无法配对的个人名单。但是......其中一些人可能会与配对列表中的成员配对。我可以将其中一个合作伙伴扔回未成对成员的池中,但这似乎会导致一个难以测试的循环,并且可能永远存在。

8 个答案:

答案 0 :(得分:1)

将标准搜索转换为概率选择的有趣想法:

  • 将历史记录加载到具有O(1)“包含”测试的结构中,例如(A,B)对的HashSet。
  • 循环通过每个0.5 * n *(n-1)个可能的配对
    • 检查此配对是否在历史记录中
    • 如果没有则继续循环的下一次迭代
    • 增加“找到数字”计数器
    • 将配对保存为“结果”,概率为1 /“找到数字”(即始终为找到的第一个未使用的配对)
  • 最后,如果“结果”有答案,那么使用它,否则所有可能性都已用尽

这将在O(n ^ 2)+ O(历史大小)中运行,并在所有概率都用完时很好地检测到这种情况。

答案 1 :(得分:1)

根据您的要求,我认为您真正需要的是准随机数,最终可以统一覆盖您的数据(即,每个人都与其他人配对一次)。准随机配对比简单的随机配对提供了更少的“聚集”结果,还有一个额外的好处是您可以更好地控制结果数据,因此您可以控制唯一配对规则而无需检测新的随机配对复制历史随机配对。

查看此维基百科条目:

http://en.wikipedia.org/wiki/Low-discrepancy_sequence

更好的阅读:

http://www.google.com/url?sa=t&source=web&cd=10&ved=0CEQQFjAJ&url=http%3A%2F%2Fwww.johndcook.com%2Fblog%2F2009%2F03%2F16%2Fquasi-random-sequences-in-art-and-integration%2F&ei=6KQXTMSuDoG0lQfVwPmbCw&usg=AFQjCNGQga_MKXJgfEQnQXy1qrHcwfOr4Q&sig2=ox7FB0mnToQbrOCYm9-OpA

我试图找到一个C#库来帮助你生成你正在寻找的那种准随机传播,但是我能找到的唯一的库是c / c ++。但我仍然建议下载源代码,因为准随机算法的完整逻辑(寻找准蒙特卡罗)就在那里:

http://www.gnu.org/software/gsl/

答案 2 :(得分:0)

在启动时,建立所有可能配对的列表。

在添加个人时将所有可能的新配对添加到此列表中,并在个人从池中删除时删除所有已过期的配对。

从此列表中随机选择新配对,并在选择配对时将其从列表中删除。

答案 3 :(得分:0)

你最好的选择可能是:

  1. 将历史记录加载到具有快速访问权限的结构中,例如(A,B)对的HashSet。
  2. 创建一组完全随机的配对(例如,通过随机改组个体列表并分割成相邻的配对)
  3. 检查每个配对是否在历史记录中(应检查(A,B)和(B,A))
  4. 如果没有找到配对,则根据需要设置全新的配对,否则转到2
  5. 请注意,如果您需要有效地创建大量新的唯一配对,则步骤1可以完成一次并在创建新配对时更新。

    另请注意,如果所有可能的配对都被用尽,您将需要采取一些额外的预防措施(在这种情况下,您需要摆脱循环!)

答案 4 :(得分:0)

怎么样:

  • 创建所有当前个人的集合CI

然后:

  • 随机选择一个A并从CI中删除
  • 通过复制CI并删除所有以前的A
  • 合作伙伴,创建一组新的可能的合作伙伴PP
  • 如果PP为空,则扫描找到的对列表,并交换A与个人C交换A,该C与不在A的历史记录中并且仍然在CI中有可能的合作伙伴的人配对。重新计算PP = A = C.
  • 如果PP不为空,则选择PP中的一个B与A配对
  • 从CI中删除B
  • 重复,直到找不到新的对

答案 5 :(得分:0)

用元素

形成一个上对角矩阵
  Individual   A   B  C  D
           A   * 
           B   *   *
           C   *   *  *
           D   *   *  *  *

如果已形成对,则每个空白元素将包含True,否则将为False。

每个配对会话包括循环遍历每一行的列,直到找到False,形成该对并将矩阵元素设置为true。

删除个人时,请删除行和列。

如果性能有问题,您可以在计数器中保留最后一对形成的行,并在删除时仔细更新

添加个人时,添加最后一行&栏第

答案 6 :(得分:0)

我认为这是一个图形问题,其中个体是节点,而顶点连接的个体尚未相关。通过这种重构,创建新对只是找到一组独立的顶点(没有任何公共节点)。

这还不是一个答案,但有可能这是众所周知的解决方案的常见图形问题。

我们可以说的一点是,在某些情况下可能没有解决方案(你必须重做以前的一对)。

考虑双重图形(顶点和节点的交换角色:节点将成对和顶点之间的公共个体)也可能更简单。

答案 7 :(得分:0)

有没有办法订购两个元素?如果是这样,您可以通过始终以相同的方式排序对,每次迭代保存一个(可能只有一半)哈希探测。因此,如果您有A,B,C和D,则生成的可能对将是[AB,CD] [AC,BD]或[AD,BC]。

我所做的就是:

pair_everyone (pool, pairs, history):
  if pool is empty:
    all done, update global history, return pairs

  repeat for pool_size/2:
    pick element1 (randomly from pool)
    pick element2 (randomly from pool)
    set pair=pair(e1, e2)
    until pair not in history or all possible pairs tried:
      pick element1 (randomly from pool)
      pick element2 (randomly from pool)
      set pair=pair(e1, e2)

    if pair is not in history:
      result=pair_everyone(pool-e1-e2, pairs+pair, history+pair)
      if result != failure:
        return result
    else:
      return failure