【问题标题】:Getting all possible combinations from a list of numbers从数字列表中获取所有可能的组合
【发布时间】:2010-07-23 15:20:40
【问题描述】:

我正在寻找一种有效的方法来实现这一目标:

  • 您有一个数字列表 1.....n(通常:1..5 或 1..7 左右 - 相当小,但可能因情况而异)

  • 您需要这些数字的所有长度的所有组合,例如只有一个数字的所有组合 ({1}, {2}, .... {n}),然后是两个不同数字的所有组合 ({1,2}, {1,3}, {1,4} 。 .... {n-1, n} ),然后是其中三个数字({1,2,3},{1,2,4})的所有组合,依此类推

基本上,在组内,顺序是无关紧要的,因此 {1,2,3} 等价于 {1,3,2} - 只需从该列表中获取所有 x 个数字组

似乎应该有一个简单的算法来解决这个问题 - 但到目前为止我已经徒劳无功了。大多数组合学和置换算法似乎 a) 考虑了顺序(例如 123 不等于 132),并且它们似乎总是对单个字符串或数字进行操作......

任何人都有一个很棒的,nice'n'quick 算法??

谢谢!

【问题讨论】:

标签: c# algorithm combinatorics


【解决方案1】:

不是我的代码,但您正在寻找 powerset。谷歌给了我这个解决方案,似乎行不通:

public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list)
{
    return from m in Enumerable.Range(0, 1 << list.Count)
              select
                  from i in Enumerable.Range(0, list.Count)
                  where (m & (1 << i)) != 0
                  select list[i];
}

来源:http://rosettacode.org/wiki/Power_set#C.23

【讨论】:

  • 只是为了澄清,这是我的答案,通过 LINQ 实现。我不得不承认,这非常聪明。
  • Linq 的力量,尊重它。
  • 有效,但仅适用于元素少于 32 个的列表,因为 Enumerable.Range 将第二个参数限制为“int”
【解决方案2】:

只需增加一个二进制数并获取与设置的位相对应的元素。

例如,00101101 意味着获取索引 0、2、3 和 5 处的元素。由于您的列表只是 1..n,因此元素就是索引 + 1。

这将生成有序排列。换句话说,只会生成{1, 2, 3}。不是{1, 3, 2}{2, 1, 3}{2, 3, 1} 等。

【讨论】:

  • @Henri 的解决方案几乎是这个想法的实现,使用 LINQ。
  • @Nate Kohl 是的,我刚刚对此发表了评论。相当聪明!给它+1。
  • +1 :一个很好的证明,一个给定大小 N 的子集的数量是 2^N
  • 这是一个很棒的答案!
【解决方案3】:

这是我过去为了完成这样的任务而写的。

List<T[]> CreateSubsets<T>(T[] originalArray) 
{ 
    List<T[]> subsets = new List<T[]>(); 

    for (int i = 0; i < originalArray.Length; i++) 
    { 
        int subsetCount = subsets.Count; 
        subsets.Add(new T[] { originalArray[i] }); 

        for (int j = 0; j < subsetCount; j++) 
        { 
            T[] newSubset = new T[subsets[j].Length + 1]; 
            subsets[j].CopyTo(newSubset, 0); 
            newSubset[newSubset.Length - 1] = originalArray[i]; 
            subsets.Add(newSubset); 
        } 
    } 

    return subsets; 
}

它是通用的,因此它适用于整数、长整数、字符串、Foos 等。

【讨论】:

  • 例如,对于List&lt;int&gt;,您可以将其称为var newList = CreateSubsets&lt;int&gt;(sourceList.ToArray())
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多