我有以下问题:
我有三个元素a,b和c。以及从0到100的整数。如何获得所有可能的组合,如下所示:
a 0 b 0 c 0
a 1 b 0 c 0
a 0 b 1 c 0
a 0 b 0 c 1
a 1 b 1 c 0
...
a 100 b 100 c 100
等等?我正在使用C#,但我想尽自己的努力独立于编程语言来找到正确的算法。不幸的是,我不太了解笛卡尔积等。
答案 0 :(得分:1)
您说要
独立于编程语言来找到正确的算法
因此,我将尝试使用最少的编程语言功能来回答这个问题。我将给出的示例假定编程语言具有可扩展的列表,数组,数组数组以及浅表克隆数组的能力。这些是常见的编程功能,因此希望可以。
要解决此问题,您需要生成3组N个整数的所有组合,其中每组包括0..N-1个整数。 (一组集合的组合集合-这就是所谓的这些集合的笛卡尔积。)
下面的解决方案使用递归,但是我们不必担心堆栈溢出,因为堆栈深度不超过要组合的集合数-在这种情况下为3。(通常使用递归,您可以尝试使用堆栈类来管理它,但这会使代码更加复杂。)
combine()
递归地遍历每个集合的所有元素,并在每个递归级别上开始处理下一个集合的元素。
因此,递归的外部级别开始在set [0]的所有元素上进行迭代,并且对于每个元素,它都使用该元素填充当前组合的下一项。
然后:如果是最后一组,则完成组合并输出。否则,将进行递归调用以开始填充下一组元素。
一旦有了所有组合,我们就可以遍历它们并穿插它们
根据您的要求使用a
,b
和c
。
将其放在一起:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var sets = createSets(3, 10);
var combinations = Combinations(sets);
foreach (var combination in combinations)
{
Console.WriteLine($"a {combination[0]} b {combination[1]} c {combination[2]}");
}
}
static int[][] createSets(int numSets, int intsPerSet)
{
int[][] sets = new int[numSets][];
// All the sets are the same, so we can just use copies of it rather than create multiples.
int[] oneSet = new int[intsPerSet];
for (int i = 0; i < intsPerSet; ++i)
oneSet[i] = i;
for (int i = 0; i < numSets; ++i)
sets[i] = oneSet;
return sets;
}
public static List<int[]> Combinations(int[][] sets)
{
var result = new List<int[]>();
combine(sets, 0, new int[sets.Length], result);
return result;
}
static void combine(int[][] sets, int set, int[] combination, List<int[]> output)
{
for (int i = 0; i < sets[set].Length; ++i)
{
combination[set] = sets[set][i];
if (set < (sets.Length - 1))
combine(sets, set + 1, combination, output);
else
output.Add((int[])combination.Clone());
}
}
}
}
Action<int[]>
并与每个组合一起调用-这样就不必通过庞大的列表返回结果。答案 1 :(得分:0)
如果输出的顺序无关紧要,那应该足够了:
for(int i = 0; i <= 100; i++){
for(int j = 0; j <= 100; j++){
for(int k = 0; k <= 100; k++){
Console.WriteLine($"a {i} b {j} c {k} ");
}
}
}
输出
a 0 b 0 c 0
a 0 b 0 c 1
a 0 b 0 c 2
a 0 b 0 c 3
...
a 100 b 100 c 100