2

可能重复:
数组的不同组合(C#)

string[] array = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10"};

如何为每个组合生成 2 / 3 / 4 / 5 个字符串,例如每个组合 2 个字符串,没有重复/重复,也无视位置,使用组合公式 nCr = 10!/2!(10-2)!= 45 种组合。

我需要输出是这样的:

"01", "02"
"01", "03"
"01", "04"
...
"02", "03" // eliminate the "02","01" 'cause it is same as "01","02" combination
"02", "04"
...

然后生成 3 个字符串的组合,将有 120 个组合(根据 nCr)。我需要输出是这样的:

"01","02","03"
"01","02","04"
...

而 4 个字符串的组合,将有 210 个组合,最少,每个组合 5 个字符串的组合,将有 252 个组合。

我该怎么写?我用了很多循环,看起来真的很乱。

4

3 回答 3

9

您可以使用简单的递归:

private static IEnumerable<string> Combinations(int start, int level)
{
  for ( int i = start; i < array.Length; i++ )
    if ( level == 1 )
      yield return array[i];
    else
      foreach ( string combination in Combinations(i + 1, level - 1) )
        yield return String.Format("{0} {1}", array[i], combination);
}

像这样称呼它:

  var combinations = Combinations(0, 2);

  foreach ( var item in combinations )
    Console.WriteLine(item);
于 2012-12-04T09:25:48.347 回答
7

您可以使用这个高效的项目:Permutations, Combinations, and Variations using C# Generics

string[] array = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" };
int lowerIndex = 2;
var combinations = new Facet.Combinatorics.Combinations<String>(
    array, 
    lowerIndex, 
    Facet.Combinatorics.GenerateOption.WithoutRepetition
);

foreach (IList<String> combis in combinations)
{
    String combi = String.Join(" ", combis);
    Console.WriteLine(combi);
}

由于它是开源的,你可以看看它是如何实现的。但是上面的链接也非常有用。

输出(lowerIndex=2):

01 02
01 03
01 04
01 05
01 06
01 07
01 08
01 09
01 10
02 03  <-- no 02 01 since it would be a repitition
02 04
02 05
// ... (45 combinations w/o repetitions)
09 10

输出(lowerIndex=5):

01 02 03 04 05
01 02 03 04 06
01 02 03 04 07
01 02 03 04 08
01 02 03 04 09
01 02 03 04 10
01 02 03 05 06
01 02 03 05 07
01 02 03 05 08
01 02 03 05 09
01 02 03 05 10
01 02 03 06 07
// ........... (252 combinations w/o repetitions)
05 07 08 09 10
06 07 08 09 10
于 2012-12-04T09:04:56.970 回答
-1

这是使用 nCr 对两个数字执行组合的函数,将其调整为多个数字

    /// <summary>
    /// Performs a nCr Combination of the two numbers
    /// </summary>
    /// <param name="n">The Number</param>
    /// <param name="r">The Range</param>
    /// <returns></returns>
    public static double Combination(double n, double r)
    {
        /*
         * Formula for Combination: n! / (r! * (n - r)!)
         */

        // n and r should be integral values
        double rfloor = Math.Floor(r);
        double nfloor = Math.Floor(n);
        // Check for all invalid values of n and r.
        if ((n < 1) || (r < 0) || (r > n) || (r != rfloor) || (n != nfloor))
        {
            throw new Exception("Invalid Input to Combination Function: Number must be greater than Range");
        }

        return Factorial(n) / (Factorial(r) * Factorial(n - r));
    }

public static double Factorial(double n)
    {
        if (n < 0) { throw new Exception("Cannot take the factorial of a negative number"); }
        double factorial = 1;
        // 0! and 1! = 1
        for (double i = 2; i < n + 1; i++)
        {
            factorial *= i;
        }
        return factorial;
    }
于 2012-12-04T09:05:21.360 回答