python中的排列太多了

时间:2015-10-22 20:50:49

标签: python algorithm permutation

我的程序需要在列表列表中包含2和0的所有组合。例如:[[0,0,0,2],[0,0,2,0],[0,2,0,0] ....]。我将在每个子列表中始终有n ^ 2个元素,其中n-1次为2。所以我应该有n ^ 2!/((n ^ 2-n)!*(n-1)!)结果。

问题是我的代码首先计算所有排列,然后删除重复项。因此,对于n = 4,将有16个!子列表,它崩溃了我的电脑。我怎样才能解决这个问题? (它需要处理至少n = 8)

以下是代码:

servers = n*n   #number of elements in each sublist
infected = n - 1 #number of 2s
grid = [ 0 for a in range(servers)] #list representing grid, with all 0s
grid = grid[:-infected] + infected * [2] #make last ones 2s

all_infections = list(itertools.permutations(grid))  # !!PROBLEM!! create all permutations of infection (touple)
all_infections = [list(a) for a in all_infections]   # Convert touple to lists


all_infections.sort()
all_infections = list(k for k,_ in itertools.groupby(all_infections)) #remove duplicates

combinations = len(all_infections)
print (all_infections)

results = []

for index in range(combinations): #calculate the infected states
    results = results + [grid_infecter(all_infections[index],n)]

1 个答案:

答案 0 :(得分:1)

你的主要问题是远远超出实际问题要求的组合爆炸。正如你所说,n = 8的情况只需要64!/(57!7!)的结果。为什么要一次性存储它们?

这给你两个基本选择:

  1. 编写自己的排列例程。这些很容易通过基本搜索找到,例如this one
  2. 从排列()构建生成器流,并在它们进入列表之前消除重复项。
  3. 像这样:

    def no_duplicate(gen):
       previous = set()
       for permutation in gen:
          if permutation not in previous:
             previous.add(permutation)
             yield permutation
    
    # Now set up a generator pipeline for the permutations
    infection_stream = (no_duplicate(itertools.permutations(grid)))
    result_stream = (grid_infecter(dish) for dish in infection_stream)
    

    result_stream是一个可以用于任何目的的生成器,例如:

    results = [_ for _ in result_stream]
    

    生成器的神奇之处在于,到目前为止,我们在任何时候都只有一个活跃的排列。独特的存储在"之前的"在no_duplicates中设置,但这是唯一存在潜在空间问题的地方。如果这超出了你的计算机内存或你的耐心(毕竟算法是O(n ^ 2!),那么你需要编写自己的排列生成器,这样你就可以一次一个地处理它们一个长期的"记住"设备。