python 在长度为2n的列表中找到所有可能的n对不重复的对?

0h4hbjxa  于 2024-01-05  发布在  Python
关注(0)|答案(1)|浏览(150)

给定一个大小为2n的列表,如何找到所有可能的n对而不重复?该算法最好是最优的,因为在我的情况下n很大。
例如,给出一个列表

  1. [1, 2, 3, 4],

字符串
它应该返回

  1. [[1, 2], [3, 4]]
  2. [[1, 3], [2, 4]]
  3. [[1, 4], [2, 3]]


一般来说,它应该返回(2n,2)* (2n-2,2) *... *(2,2)2D列表,其中(n,m)是在n个项目中挑选m个项目的组合数。
我使用的是Python 3。我尝试了Python itertools.combinations,通过3个步骤以蛮力的方式解决了这个问题:
1.求所有有序对[i,j],i<j,例如在上面的例子中,我们有[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]。
1.使用itertools.combinations将上述对合并组合成n对,例如它有[[1,2],[1,3]]等
1.在步骤2中,通过将它们展平为1D,然后使用Python set,然后比较长度来删除重复的对,即[[1,2],[1,3]]是坏的,因为1是重复的。这个列表对应的集合是{1,2,3},其长度为3但不是4。因此,它被删除。

**我的目标是加速算法,而不是使用上面的蛮力方法,因为在我的情况下n很大。

jgzswidk

jgzswidk1#

首先,你对组合数的计算是错误的,正如你的简单例子所示。choose(4,2)* choose(2,2)= 6 * 1 = 6,然而,正如你所看到的,只有三种可能性。您不希望算法同时产生[[1, 2], [3, 4]][[3, 4], [1, 2],但认为它们是相同的结果。您需要进行计算并除以在n!
也就是说,看看所有的结果,就像你上面看到的那样,

  1. [[x1, y1], [x2, y2], [x3, y3], .....]

字符串
规范表示是其中x1 < x2 < x3 < ....x1 < y1x2 < y2x3 < y3,.
由此,很容易看出x1必须是1,x2必须是去除x1y1后的所有元素中最小的,x3必须是去除x1x2y1y2后的所有元素中最小的。
这给了你一个很好的递归算法:

  1. def generate(n):
  2. def internal(prefix, items):
  3. if not items:
  4. yield prefix
  5. else:
  6. for index in range(1, len(items)):
  7. x = items[0]
  8. y = items[index]
  9. # The list of all pairs we've seen so far
  10. new_prefix = [*prefix, [x, y]]
  11. # Remove the 0-th and i-th elements from items
  12. new_items = items[1:index] + items[index + 1:]
  13. yield from internal(new_prefix, new_items)
  14. items = list(range(1, 2 * n + 1))
  15. return list(internal([], items))

展开查看全部

相关问题