深度优先组合算法

时间:2014-01-08 00:00:10

标签: algorithm combinations combinatorics

假设我有以下数组:

A = [
  ['a', 'b', 'c'],
  ['d', 'e', 'f'],
  ['g', 'h'],
  ['i'],
  ['j', 'k', 'l']
]

我想找到每个数组元素与其他数组元素的所有可能组合(即'adgij'是一种可能性,但不是'abcde')。

我可以强制它,只需循环这样的一切(javascript):

var A = [
      ['a', 'b', 'c'],
      ['d', 'e', 'f'],
      ['g', 'h'],
      ['i'],
      ['j', 'k', 'l']
    ],
    combinations,
    newCombinations = [];

A.forEach(function(a, index) {
  newCombinations = [];

  if (index === 0) {
    newCombinations = a;
  } else {
    a.forEach(function(val){
      combinations.forEach(function(combination){
        newCombinations.push(combination + val);
      });
    });
  }

  combinations = newCombinations;
});

这种方法的问题在于它是广度优先的,所以如果我想在n次迭代后停止,我会有不完整的组合。

有没有办法使用深度优先方法获得所有可能的组合?

2 个答案:

答案 0 :(得分:3)

伪代码中的简单递归函数。

每个递归步骤从当前索引的数组中选取一个元素,并为下一个索引调用该函数。

current可以只是一个列表。

printAllCombinations(A, {}, 0)

printAllCombinations(A, current, index)
  if index == A.length
    print current
    return
  for each element e in A[index]
    current.addToBack(e)
    printAllCombinations(A, current, index + 1)
    current.removeLast(e)

答案 1 :(得分:0)

我基本上创建了一个地图(例如[0,0,0,0,0]会选择列表列表中的所有第一个成员,而[2,2,1,0] ,2]将在python中选择所有最后成员)到数字,然后转换回列表。这有点棘手,但我希望我是对的:

#!/usr/bin/env python
import itertools

def map_good_opt(good_opt, A):
    return [i[1][i[0]] for i in zip(good_opt, A)]

if "__main__" == __name__:

    # your list of lists    
    A = [
          ['a', 'b', 'c'],
          ['d', 'e', 'f'],
          ['g', 'h'],
          ['i'],
          ['j', 'k', 'l']
        ]

    # this part generates all options (a bit more actually...)
    m = max(len(a) for a in A)
    print "m : %d" % m
    nums = range(m)
    print "nums: %r" % str(nums)
    opts = itertools.product(nums, repeat=len(A))       

    # now we have all number 00000 - 33333
    # we don't want 33333 or anything higher than len(A[i]) for each list in A 
    opts = itertools.product(nums, repeat=len(A))
    # this removes all bad options... (I hope :D)
    good_opts = [opt for opt in opts if len([i for i in range(len(A)) if (opt[i] < len(A[i]))]) == len(A)]

    # and we're left with the good options
    for opts in good_opts:
        print str(opt)
    print "GO: %d" % len(good_opts)
    for g in good_opts:
        print str("OPTIONS: " + str(g))
        print str("MAPPED TO: " + str(map_good_opt(g,A)))
    print "done."

我这样做只是为了学习我最近在Stackoverflow中学到的itertoolszip,你的问题看起来很有趣,可以测试这个:) 祝你好运。