需要找出并存储在锯齿数组的所有组合

本文关键字:数组 组合 存储 | 更新日期: 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位(系统中有足够的空闲内存)。

但是,最好只是惰性地、动态地生成这些组合——只生成当前情况下需要的组合。