假设您有一组值(1
, 1
, 1
, 12
, 12
, 16
),您将如何生成总和在预定义范围内的所有可能组合(不重复)[min,max]
。例如,以下是范围在13
和之间的所有(所有深度的)组合17
:
1
12
1
1
12
1
1
1
12
16
1
16
1
12
这假设相同值的每个项目是无法区分的,因此您在最终输出中没有三个结果。蛮力是可能的,但在项目数量很大的情况下,所有深度的组合数量是天文数字。在上面的示例中,所有深度都有 (3 + 1) * (2 + 1) * (1 + 1) = 24 种组合。因此,总组合是任何给定值的项目数 + 1 的乘积。当然我们可以在逻辑上抛出部分和大于最大值的大量组合(例如,集合16
12
已经大于最大值的值17
,因此请跳过其中包含 a16
和12
的任何组合)。
我最初认为我可以将输入数组转换为两个数组并像里程表一样增加它们。但是我完全陷入了这种提前中断的递归算法上。有什么建议么?
{
int uniqueValues = 3;
int[] maxCounts = new int[uniqueValues];
int[] values = new int[uniqueValues];
// easy code to bin the data, just hardcoding for example
maxCounts[0] = 3;
values[0] = 1;
maxCounts[1] = 2;
values[1] = 12;
maxCounts[2] = 1;
values[2] = 16;
GenerateCombinationsHelper(new List<int[]>(), 13, 17, 0, 0, maxCounts, new int[3], values);
}
private void GenerateCombinationsHelper(List<int[]> results, int min, int max, int currentValue, int index, int[] maxValues, int[] currentCombo, int[] values)
{
if (index >= maxValues.Length)
{
return;
}
while (currentCombo[index] < maxValues[index])
{
currentValue += values[index];
if (currentValue> max)
{
return;
}
currentCombo[index]++;
if (currentValue< min)
{
GenerateCombinationsHelper(results, min, max, currentValue, index + 1, maxValues, currentCombo, values);
}
else
{
results.Add((int[])currentCombo.Clone());
}
}
}
编辑
整数值仅用于演示。它可以是任何具有某种数值的对象(int
、double
、float
等...)
通常只有少数唯一值(约 10 个左右),但可能有数千个项目。