【问题标题】:Ordered Unique Combinations [closed]有序的独特组合[关闭]
【发布时间】:2014-03-19 18:41:11
【问题描述】:

我有以下课程:

internal class Course
{
    public int CourseCode { get; set; }
    public string DeptCode { get; set; }
    public string Name { get; set; }
}

以下代码是我拥有的二维数组:

Course[][] courses = new Course[3][];
courses[0] = new Course[] {
   new Course() { CourseCode = 100, DeptCode = "EGR", Name = "EGR A" },
   new Course() { CourseCode = 100, DeptCode = "EGR", Name = "EGR B" }
};

courses[1] = new Course[] {
   new Course() { CourseCode = 200, DeptCode = "EN", Name = "EN A" }
};

courses[2] = new Course[] {
   new Course() { CourseCode = 300, DeptCode = "PHY", Name = "PHY A" }
};

我想要做的是获得一个组中的每个项目可以与其他组进行的不同组合;例如使用前面的代码,结果将是:

1. EGR A - EN A - PHY A
2. EGR B - EN A - PHY A

答案: 要获得可能的组合数量,我们可以使用Rule of Product,在上述情况下,可能的组合将是(2 * 1 * 1) = 2,这确实是我上面写的2个组合。

LordTakkera 给出了完美的答案,非常感谢!

【问题讨论】:

  • 很抱歉,如果我让它看起来像我希望人们为我编写代码。我的第一次尝试是我编写了一个代码,其中我有一个数组 Course[],所有可能的课程都没有分组。然后我得到了所有可能的组合,在这种情况下,n 是 7,k 是 3。然后我过滤所有结果以删除包含在一组中的重复项,以不允许在同一数组中包含相同类别的课程。虽然这是一个非常耗时的过程,所以我尝试找到另一种方法来做到这一点,这就是上面列出的方法。我尝试了很多 for 循环,但无法让它工作。 ://

标签: c# arrays combinations


【解决方案1】:

您可以使用嵌套的 for 循环:

for (int i = 0; i < courses[0].Length; i++)
{
   for (int j = 0; j < courses[1].Length; i++)
   {
     for (int k = 0; k < courses[2].Length; i++)
     {
         //Do whatever you need with the combo, accessed like:
         //courses[0][i], courses[1][j], courses[2][k]
     }
   }
}

当然,您需要的嵌套越多,这个解决方案就会变得非常混乱。如果您需要更深入,我会使用某种递归函数来遍历集合并生成组合。

应该是这样的:

class CombinationHelper
{
    public List<List<Course>> GetAllCombinations(Course[][] courses)
    {
            return GetCourseCombination(courses, 0);
    }

    public List<List<Course>> GetCourseCombination(Course[][] courses, int myIndex)
    {
        List<List<Course>> combos = new List<List<Course>>();

        for (int i = 0; i < courses[myIndex].Length; i++)
        {
            if (myIndex + 1 < courses.GetLength(0))
            {
               foreach (List<Course> combo in GetCourseCombination(courses, myIndex + 1))
               {
                  combo.Add(courses[myIndex][i]);
                  combos.Add(combo);
               }
            }
            else
            {
               List<Course> newCombination = new List<Course>() { courses[myIndex][i] };
               combos.Add(newCombination);
            }
        }
        return combos;
    }
}

我对此进行了测试(用“int”代替“Course”以使验证更容易),它产生了所有 8 种组合(虽然不是按顺序,但递归往往会这样做。如果我想出订购代码,我会发布,但应该不会困难)。

递归函数对我来说已经够难了,所以我的解释不会很好。基本上,我们从“0”索引开始整个事情(这样我们从头开始)。然后我们遍历当前数组。如果我们不是“主”数组中的最后一个数组,我们将递归到下一个子数组。否则,我们创建一个新组合,将自己添加到其中,然后返回。

随着递归堆栈“展开”,我们将生成的组合添加到返回列表中,将我们自己添加到其中,然后再次返回。最终,整个事情“展开”,你只剩下所有组合的一个列表。

再一次,我确信这是一个非常令人困惑的解释,但递归算法(至少对我而言)本质上是令人困惑的。我很乐意尝试详细说明您想要的任何观点。

【讨论】:

  • 非常感谢!这可行,但由于数组是动态的,我不能依赖于编写 2 个嵌套循环。取决于用户输入,它可能更多,也可能更少。另外,您的意思也是 j++ 和 i++,对吧?我的最终目标是通过 course[][] 数组并找到不同的独特组合,就像你提到的代码一样,但对于任何数组维度。再次感谢:)
  • 是的,我的意思是 j++ 和 k++。稍后我将发布一个递归形式的示例,这可能是您想要的方式。
  • 我的脑袋现在因为计算出太多的递归而爆炸:) 检查我的例子,让我知道你的想法!对于没有订购,我提前道歉。
  • 尝试将行改为i &lt; courses[myIndex].Length
  • 编辑我的答案以反映修复
【解决方案2】:

看看你的第二个索引 - 0 或 1。如果你只看那个,你会看到一个从 0 到 7 的二进制数。

从 0 数到 7,将其转换为位,得到你需要的组合模式。

【讨论】:

  • +1 用于调用按位操作,嵌套的 for 循环可能会更简单一些:)
  • 我不确定,我会把它留给 OP。如果我是 OP,我会使用二进制表示来练习。
  • 非常感谢您的回答! :) 不幸的是,我对按位运算知之甚少,所以我不知道如何将您的想法付诸实践。如果您能引导我走向正确的方向,我将不胜感激 :) 谢谢!
  • 我也刚刚意识到,当索引需要为“2”时会出现问题,因为它会给样本数据。不知道如何在仍然以二进制计数的同时修复该部分:(。仍然是一个非常聪明的方法!
  • 如果需要,以 3、4 或 17 为底数。
猜你喜欢
  • 2020-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多