【问题标题】:Partial Combinations/Permutations in C# - e.g. A,B,C = {A,B}, {A,C}, {B,C}C# 中的部分组合/排列 - 例如A,B,C = {A,B}, {A,C}, {B,C}
【发布时间】:2016-10-25 10:26:04
【问题描述】:

排列有很多brilliant 实现 - 我在链接中选择了 Sam 的答案。

我也知道排列和组合之间存在差异,但我不知道如何正确表达。

我需要有关获取所有独特部分组合的指导,例如

A,B,C = {A,B}, {A,C}, {B,C}
A,B,C,D = {A,B,C},{A,B,D},{B,C,D},{A,C,D},{A,B}, {A,C}, {B,C}

从这里我将把它传递给排列函数,让我全部可用 排列, 例如{A,B}, {B,A}, {A,C}, {C,A}

如何获得更大集合的这些(部分)子集?

【问题讨论】:

  • 你想在方法上做什么样的签名?它是否总是返回缺少一项的集合,或者您可能想传入一个四项集并获取所有 2 项子集?或者您可能想要获得所有 2 和所有三个子集?从你的例子中有点不清楚你到底想要什么......
  • 抱歉不清楚,我现在更新了这个问题来解决这个问题。例如4 个项目,这将是所有 2 个项目子集和 3 个项目子集。因此所有组合 > 1 和
  • 为什么第一种情况不包括 {A,B,C}, {A}, {B} 和 {C}?这些也是 {A,B,C} 的子集
  • 道歉@JanKukacka,我现在更新了问题,我只对子集感兴趣,而不是完整集,而不是单集。这是我正在与之斗争的所有组合
  • @RBarryYoung 我意识到这有点太晚了,但我撤回了我的近距离投票。

标签: c# combinations permutation


【解决方案1】:

递归很容易做到。你在GetSubCombinations 函数中遍历一个虚拟树,总是首先返回没有当前元素的集合,然后返回当前元素。在最后一级(GetSubCombinations 函数的第一部分)生成要返回的列表,包括最后一个元素或为空。

代码如下:

using System.Collections.Generic;


class Program {
    private static IEnumerable<List<char>> GetSubCombinations(char[] elements, uint startingPos)
    {
        // Leaf condition
        if (startingPos == elements.Length - 1)
        {
            yield return new List<char> {elements[startingPos]};
            yield return new List<char>();
            yield break;
        }

        // node splitting
        foreach (var list in GetSubCombinations(elements, startingPos + 1))
        {
            yield return list;
            list.Add(elements[startingPos]);
            yield return list;
            list.Remove(elements[startingPos]);
        }
    }

    private static IEnumerable<List<char>> GetPartialCombinations(char[] elements)
    {
        foreach (var c in GetSubCombinations(elements, 0))
        {
            // Here you can filter out trivial combinations,
            // e.g. all elements, individual elements and the empty set
            if (c.Count > 1 && c.Count < elements.Length)
                yield return c;
        }
    }


    static void Main(string[] args) {
        char[] elements = new char[] {'A', 'B', 'C'};
        foreach (var combination in GetPartialCombinations(elements))
        {
            foreach (char elem in combination)
                System.Console.Write(elem + ", ");
            System.Console.Write("\n");
        }
        return;
    }

}

【讨论】:

    【解决方案2】:

    排列与组合之间的区别在于排列中的顺序很重要。

    据我了解,您想要所有组合, 因此,所有未填充确切集合的组合(您想制作一个子集)

    前:

    所以对于S = {A,B,C,D},部分组合的示例是{A,C,B},因为它不关心顺序并且不包含完整集合(即它是 S 的子集)

    组合的公式是N choose K

    所以你的集合有 4 个元素 (N),而你想要 3 个或更少 (K) 的集合

    So N!/K!(N-K)! 
    3: = 4!/3!(4-3)! = (1x2x3x4)/(1x2x3)(1) = 4
    2: = 4!/2!(2)! = 1x2x3x4/(1x2x1x2) = 6
    1: = 4!/1!(4-1)! = 1x2x3x4/1x2x3 = 4
    

    因此答案是14

    如果你想要一些关于如何实现组合计算的代码:SOURCE

    private static void GetCombination(List<int> list)
    {
        double count = Math.Pow(2, list.Count);
        for (int i = 1; i <= count - 1; i++)
        {
            string str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
            for (int j = 0; j < str.Length; j++)
            {
                if (str[j] == '1')
                {
                    Console.Write(list[j]);
                }
            }
            Console.WriteLine();
        }
    }
    

    【讨论】:

    • 对不起,我忘了添加答案部分。 (现在就在里面)
    • 这通过什么方式生成所有部分组合子集?它似乎只是计算有多少,而不是实际生成子集。
    • @TristanvanDam 这就是所需要的。我排除了全部元素和单个元素,但确实如此。
    • 这用于生成您想要四个字母中的三个字母的子集。即:{A,B,C}, {B,C,D}, {C,D,A}, {D,A,B}。请注意它们的顺序,因为它是一个组合。您将对每个相关子集 (S2) 和 (S1) 执行相同操作
    • @PeterPitLock 我已经重写它以使其更清晰
    猜你喜欢
    • 2011-08-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    相关资源
    最近更新 更多