C# 查找列表的所有子集

C# 查找列表的所有子集,c#,list,loops,combinations,C#,List,Loops,Combinations,我有一个列表,我需要输出列表的每个子集 例如a b c d e 将输出到 a b c d e ab ac ad ae abc abd abe bcd bce .... abcde 我认为正确的术语是组合,不应在同一行上重复任何元素 我本打算用一系列的循环来尝试,但我甚至不确定wehre是否会开始 有什么建议吗?这是我写的一些代码。它构造了一个字母表中所有可能字符串的列表,长度为1到maxLength:换句话说,我们正在计算字母表的幂 s

我有一个列表,我需要输出列表的每个子集

例如a b c d e

将输出到

 a
 b
 c  
 d 
 e 
 ab  
 ac  
 ad 
 ae

 abc
 abd 
 abe
 bcd
 bce
 ....
 abcde
我认为正确的术语是组合,不应在同一行上重复任何元素

我本打算用一系列的循环来尝试,但我甚至不确定wehre是否会开始


有什么建议吗?

这是我写的一些代码。它构造了一个字母表中所有可能字符串的列表,长度为1到maxLength:换句话说,我们正在计算字母表的幂

  static class StringBuilder<T>
  {
    public static List<List<T>> CreateStrings(List<T> alphabet, int maxLength)
    {
      // This will hold all the strings which we create
      List<List<T>> strings = new List<List<T>>();

      // This will hold the string which we created the previous time through
      // the loop (they will all have length i in the loop)
      List<List<T>> lastStrings = new List<List<T>>();
      foreach (T t in alphabet)
      {
        // Populate it with the string of length 1 read directly from alphabet
        lastStrings.Add(new List<T>(new T[] { t }));
      }

      // This holds the string we make by appending each element from the
      // alphabet to the strings in lastStrings
      List<List<T>> newStrings;

      // Here we make string2 for each length 2 to maxLength
      for (int i = 0; i < maxLength; ++i)
      {
        newStrings = new List<List<T>>();
        foreach (List<T> s in lastStrings)
        {
          newStrings.AddRange(AppendElements(s, alphabet));
        }
        strings.AddRange(lastStrings);
        lastStrings = newStrings;
      }

      return strings;
    }

    public static List<List<T>> AppendElements(List<T> list, List<T> alphabet)
    {
      // Here we just append an each element in the alphabet to the given list,
      // creating a list of new string which are one element longer.
      List<List<T>> newList = new List<List<T>>();
      List<T> temp = new List<T>(list);
      foreach (T t in alphabet)
      {
        // Append the element
        temp.Add(t);

        // Add our new string to the collection
        newList.Add(new List<T>(temp));

        // Remove the element so we can make another string using
        // the next element of the alphabet
        temp.RemoveAt(temp.Count-1);
      }
      return newList;
    }
  }

扩展while循环行上的某些内容:

<?

$testarray[0] = "a";
$testarray[1] = "b";
$testarray[2] = "c";
$testarray[3] = "d";
$testarray[4] = "e";


$x=0;
$y = 0;
while($x<=4) {

$subsetOne[$x] .= $testarray[$y];
$subsetOne[$x] .= $testarray[$x];

$subsetTwo[$x] .= $testarray[$y];
$subsetTwo[$x] .= $subsetOne[$x];

$subsetThree[$x] = str_replace("aa","ab",$subsetTwo[$x]);

$x++;
}



?>

这将生成您想要的集合,但以不同的顺序(我在末尾按字母表排序),您也会希望按长度排序

你最终会得到:

a ab abc abcd abcde abce ... D 判定元件 e

因此,除了空字符串之外,所有可能的子集都将保持原始列表的顺序

想法是将每个元素添加到一个不断增长的列表中。对于每个新元素,首先添加它,然后将其添加到所有现有元素中

所以,从“a”开始

转到“b”。将其添加到列表中。我们现在有{'a','b'}

将它添加到现有元素中,这样我们就有了“ab”。现在我们有{'a','b','ab'}

然后是'c',并将其添加到现有元素中,以获得'ac','bc','abc':{'a','b','ab','c','ac','bc',abc'}。等等,直到我们完成为止

        string set = "abcde";

        // Init list
        List<string> subsets = new List<string>();

        // Loop over individual elements
        for (int i = 1; i < set.Length; i++)
        {
            subsets.Add(set[i - 1].ToString());

            List<string> newSubsets = new List<string>();

            // Loop over existing subsets
            for (int j = 0; j < subsets.Count; j++)
            {
                string newSubset = subsets[j] + set[i];
                newSubsets.Add(newSubset);
            }

            subsets.AddRange(newSubsets);
        }

        // Add in the last element
        subsets.Add(set[set.Length - 1].ToString());
        subsets.Sort();

        Console.WriteLine(string.Join(Environment.NewLine, subsets));

如果您所需要的只是原始列表中元素的组合,那么可以将问题转化为以下内容:您有一个大小为N的位数组,并且希望为数组中的元素找到所有可能的选择。例如,如果您的原始列表是

a、b、c、d、e

那么你的阵列就可以

01 0 0 0

其结果是输出

b

或者数组可以是

10110

返回

acd

这是一个简单的递归问题,可以在O2^n时间内解决

编辑添加递归算法的伪代码:

CreateResultSet(List<int> currentResult, int step)
{
    if (the step number is greater than the length of the original list)
    {
        add currentResult to list of all results
        return
    }
    else
    {
        add 0 at the end of currentResult
        call CreateResultSet(currentResult, step+1)

        add 1 at the end of currentResult
        call CreateResultSet(currentResult, step+1)
    }
}

for every item in the list of all results
display the result associated to it (i.e. from 1 0 1 1 0 display acd)

这将适用于任何集合。我对答案稍加修改

    static List<List<T>> GetSubsets<T>(IEnumerable<T> Set)
    {
        var set = Set.ToList<T>();

        // Init list
        List<List<T>> subsets = new List<List<T>>();

        subsets.Add(new List<T>()); // add the empty set

        // Loop over individual elements
        for (int i = 1; i < set.Count; i++)
        {
            subsets.Add(new List<T>(){set[i - 1]});

            List<List<T>> newSubsets = new List<List<T>>();

            // Loop over existing subsets
            for (int j = 0; j < subsets.Count; j++)
            {
                var newSubset = new List<T>();
                foreach(var temp in subsets[j])
                    newSubset.Add(temp);

                newSubset.Add(set[i]);


                newSubsets.Add(newSubset);
            }

            subsets.AddRange(newSubsets);
        }

        // Add in the last element
        subsets.Add(new List<T>(){set[set.Count - 1]});
        //subsets.Sort();

        return subsets;
    }
**如果我有一组字符串,我会将其用作:


复制的??AAAA不是b c d e的子集。你想要的结果的实际定义是什么?显然,您原始列表中的元素可以重复,但要重复多少次?他似乎想要所有大小为1到N的集合,这些集合可以使用原始集合中的任意数量的项目形成。同意@vlad,如果您的两个字母序列已经消失了ae ba bb bc。。。你应该更清楚一点,你要的是这些字符的所有序列,但你略过了。同意Ron的说法,可能会用最长5个单词来表达,可以从字母表{a,b,c,d,e}中形成。我在最初的答案中有类似的代码,但事实证明,提问者最初并不清楚,这不是他需要的解决方案。这是正确的,我最初想用某种二进制开关打开每个组合,但我不确定如何对其进行编码。这看起来很有效,我必须稍微修改一下,但这是一个巨大的帮助