使用C#,我需要找出英国国家彩票可能结果的所有组合(不包括奖金编号)。因此,我试图从数字1到59的唯一组合中获得六个数字的所有组合。每个组合由非重复数字组成,顺序无关。
所有有效组合的输出为:
1 2 3 4 5 6
1 2 3 4 5 7
...依此如1 2 3 4 5 59
1 2 3 4 6 7
。 ..依据如下:54 54 55 56 57 58
53 54 55 56 57 59
54 55 56 57 58 59
由于有超过4500万个组合,我试图用一个锯齿状数组作为结果集来实现它,但是它会抛出内存异常。
所以我将它分成两个结果集,如下面的代码所示,但它仍然抛出相同的异常。
如何在两个结果集或一个结果集中获得所有组合结果集?
在下面的代码中,我使用了Jagged Arrays,但结果集可以是任何对象类型。
我显然需要在时间和空间复杂度方面具有最佳性能的算法。
感谢您的帮助。
private void GetAllCombinationsForSixNumbers(out int[][] arrayOfAllCombinationsFirstSet, out int[][] arrayOfAllCombinationsSecondSet)
{
arrayOfAllCombinationsFirstSet = new int[25000000][];
arrayOfAllCombinationsSecondSet = new int[25000000][];
for (int eachArray = 0; eachArray < arrayOfAllCombinationsFirstSet.Length; eachArray++)
{
arrayOfAllCombinationsFirstSet[eachArray] = new int[6];
arrayOfAllCombinationsSecondSet[eachArray] = new int[6];
}
int arrayCurrentRowIndex = 0, arrayCurrentRowIndexForSecondArray = 0;
for (int firstNumber = 1; firstNumber < 59; firstNumber++)
{
for (int secondNumber = firstNumber + 1; secondNumber <= 59; secondNumber++)
{
for (int thirdNumber = secondNumber + 1; thirdNumber <= 59; thirdNumber++)
{
for (int fourthNumber = thirdNumber + 1; fourthNumber <= 59; fourthNumber++)
{
for (int fifthNumber = fourthNumber + 1; fifthNumber <= 59; fifthNumber++)
{
for (int sixthNumber = fifthNumber + 1; sixthNumber <= 59; sixthNumber++)
{
if (arrayCurrentRowIndex < arrayOfAllCombinationsFirstSet.Length)
{
arrayOfAllCombinationsFirstSet[arrayCurrentRowIndex][0] = firstNumber;
arrayOfAllCombinationsFirstSet[arrayCurrentRowIndex][1] = secondNumber;
arrayOfAllCombinationsFirstSet[arrayCurrentRowIndex][2] = thirdNumber;
arrayOfAllCombinationsFirstSet[arrayCurrentRowIndex][3] = fourthNumber;
arrayOfAllCombinationsFirstSet[arrayCurrentRowIndex][4] = fifthNumber;
arrayOfAllCombinationsFirstSet[arrayCurrentRowIndex][5] = sixthNumber;
arrayCurrentRowIndex++;
}
else
{
arrayOfAllCombinationsSecondSet[arrayCurrentRowIndexForSecondArray][0] = firstNumber;
arrayOfAllCombinationsSecondSet[arrayCurrentRowIndexForSecondArray][1] = secondNumber;
arrayOfAllCombinationsSecondSet[arrayCurrentRowIndexForSecondArray][2] = thirdNumber;
arrayOfAllCombinationsSecondSet[arrayCurrentRowIndexForSecondArray][3] = fourthNumber;
arrayOfAllCombinationsSecondSet[arrayCurrentRowIndexForSecondArray][4] = fifthNumber;
arrayOfAllCombinationsSecondSet[arrayCurrentRowIndexForSecondArray][5] = sixthNumber;
arrayCurrentRowIndexForSecondArray++;
}
}
}
}
}
}
}
}
答案 0 :(得分:2)
因此,您在数字系统中生成从[1 2 3 4 5 6]到[54 55 56 57 58 59]的值,基数为59,不包括零。 排除的零根本不是问题,你只需要向左移动,所以1变为0,2变为1,依此类推。所以你的边界变成这样:
[0 1 2 3 4 5]
....
[53 54 55 56 57 58]
之后,您可以创建将索引与基数10(十进制)映射到数组中的精确值的函数。
为此,您需要将索引与基数10转换为数字系统中的索引,基数为59.例如,我想从索引123的数组中获取值:
123 => [2 5]
使用起始索引在此数字系统中添加:
[0 1 2 3 4 5] + [2 5] = [0 1 2 3 6 10]
然后你只需向后移动它:
[1 2 3 4 7 11]
至于重复 - 只需过滤它。它的总体影响可能会很小。
答案 1 :(得分:0)
如果您确实需要这么多阵列(我真的不知道您为什么会这样做),那么除了int
之外,您可以将所有byte
更改为int eachArray
,因为{{1}在CLR中需要最少的内存。此外,您可以将数组大小从byte
减少到25000000
。
在我的测试中,如果你在一个空的控制台应用程序中创建它们,那么字节数组(你的其他未改变的代码)几乎不适合32位进程的可用内存。
如果它们仍然不适合您特定应用程序的内存,那么您必须将进程更改为64位(系统中有足够的可用RAM)。
但是,只是在当前情况下,只需要懒得和动态生成组合就好得多。