【问题标题】:Is there effective algorithm that will return all different combination?是否有有效的算法可以返回所有不同的组合?
【发布时间】:2011-07-06 17:15:30
【问题描述】:

已编辑:我的意思是组合而不是排列

是否有有效算法可以返回给定数组的所有不同排列? [“A”,“B”,“C”,“D”,“E”,“F”,“G”,“H”,“I”,“J”,“K”,...]

例如:AB,AC,AD,..,DE,..,HI,..,ABC,ABD,...,DEF,..,CDEFG,...,ABCDEFGHIJK,..

我找到了一些算法,但它们返回所有排列而不是不同的排列。 不同我的意思是:

  1. AB & BA 是相同的排列

  2. DEF & FED & EFD & DFE 是相同的排列,

【问题讨论】:

标签: algorithm combinations


【解决方案1】:

我能想到的最好的方法是二进制计数器:

 A B C
-------
 0 0 0 | Empty Set
 0 0 1 | C
 0 1 0 | B
 0 1 1 | BC
 1 0 0 | A
 1 0 1 | AC
 1 1 0 | AB
 1 1 1 | ABC

【讨论】:

  • +1 用于展示二进制计数器如何工作的漂亮表格。
  • 答案将是 2^n,其中 n = 字母数。
  • 啊,是的,大 O。我应该这么说的。
【解决方案2】:

任何给定的项目要么在组合中,要么不在。为每个项目考虑一个布尔标志,说明它是否在组合中。如果您浏览了所有可能的布尔标志值列表,那么您已经浏览了所有组合。

布尔值列表也称为二进制整数。

如果您有 A-K 项,则您有 11 项。因此,遍历所有可能的 11 位数字。在 Java 中:

for (int flags = 0; flags < (1 << 11); ++flags) {
    int x = indexOfSomeItemFromZeroToTen();
    boolean isInCombination = ((i >> x) & 1) == 1;
}

如果您想跳过空组合,请从 1 而不是 0 开始。

【讨论】:

  • 应该是 ++flags 而不是 ++i?
【解决方案3】:
  1. 正如 cmets 所指出的,您希望枚举所有子集,而不是排列。

  2. 最简单的方法是使用二进制计数器。例如,假设你有 n 个元素,那么这样的东西可以在 C 中工作:

代码:

for(int i=0; i<(1<<n); ++i)  {
   //Bits of i represent subset, eg. element k is contained in subset if i&(1<<k) is set.
}

我希望这有助于回答您的问题

【讨论】:

    【解决方案4】:

    这是我编写并使用了一段时间的一些 Ruby 代码,它遍历数组中的每个组合。

    def _pbNextComb(comb,length) # :nodoc:
     i=comb.length-1
     begin
      valid=true
      for j in i...comb.length
       if j==i
        comb[j]+=1
       else
        comb[j]=comb[i]+(j-i)
       end
       if comb[j]>=length
        valid=false
        break
       end
      end
      return true if valid
      i-=1
     end while i>=0
     return false
    end
    
    #
    # Iterates through the array and yields each
    # combination of _num_ elements in the array
    #
    # Takes an array and the number of elemens
     # in each combination
    def pbEachCombination(array,num) 
     return if array.length<num || num<=0
     if array.length==num
      yield array
      return
     elsif num==1
      for x in array
       yield [x]
      end
      return
     end
     currentComb=[]
     arr=[]
     for i in 0...num
      currentComb[i]=i
     end
     begin
      for i in 0...num
       arr[i]=array[currentComb[i]]
      end
      yield arr
     end while _pbNextComb(currentComb,array.length)
    end
    

    【讨论】:

      【解决方案5】:

      这些不是排列。 ABC排列{ABC, ACB, BCA, BAC, CAB, CBA}。您有兴趣查找{A,B,C, ..., K, ...}所有不同子集(也称为power set)。这很容易做到:可以包含或排除每个元素。这是一个递归算法:

      power_set(U) =
         if U == {} then
            {{}};     
         else 
            union( { first(U), power_set(tail(U)) },  // include
                   { power_set(tail(U)) }             // exclude
                 );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-01
        • 1970-01-01
        相关资源
        最近更新 更多