需要找出并存储在锯齿数组的所有组合
本文关键字:数组 组合 存储 | 更新日期: 2023-09-27 18:12:02
使用c#,我需要找出英国国家彩票可能结果的所有组合(不包括奖金号码)。所以我试着从数字1到59的唯一组合中找出所有6个数字的组合。每个组合由不重复的数字组成,顺序无关。
所有有效组合的输出如下:
1 2 3 4 5 6
1 2 3 4 5 7
…所以on
1 2 3 4 5 59
1 2 3 4 6 7
…所以
53 54 55 56 57 58
53 54 55 56 57 59
54 55 56 57 58 59
由于有超过4500万个组合,我试图用一个锯齿数组作为结果集来实现它,但它抛出了内存异常。
所以我把它分成两个结果集,就像下面的代码一样,但它仍然抛出相同的异常。
如何在两个结果集或一个结果集中获得所有的组合?
在下面的代码中,我使用了锯齿数组,但是结果集可以是任何对象类型。
显然,我需要在时间和空间复杂度方面都具有最佳性能的算法。
提前感谢您的帮助。
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++;
}
}
}
}
}
}
}
}
那么,您生成的值从[1 2 3 4 56]到[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]
对于重复-只是过滤它。这很严重,但对性能的影响很小。
如果你绝对需要这么多数组(我真的不知道你为什么会),那么你可以将所有int
更改为byte
,除了int eachArray
,因为byte
需要CLR中最少的内存。此外,您可以将数组大小从25000000
减小到22600000
。
在我的测试中,如果你在一个空的控制台应用程序中创建字节数组,那么字节数组(其他未更改的代码)几乎不适合32位进程的可用内存。
如果它们仍然不适合您的特定应用程序的内存,那么您必须将进程更改为64位(系统中有足够的空闲内存)。
但是,最好只是惰性地、动态地生成这些组合——只生成当前情况下需要的组合。