当前位置: 首页 > 知识库问答 >
问题:

使用有限的内存查找缺失的数字

冯泓
2023-03-14

问题是,给定一个具有40亿个唯一整数的输入文件,提供一种算法来生成文件中不包含的整数,假设只有10 MB的内存。

在下面搜索了一些解决方案并发布了代码,其中一个是将整数存储到位向量块中(每个块表示40亿范围内的特定整数范围,块中的每个位表示一个整数),并为每个块使用另一个计数器来计算每个块中的整数数。因此,如果整数的数量小于整数的块容量,则扫描块的位向量以查找缺少的整数。

我对此解决方案的问题是,为什么“我们选择的越接近中间位置,在任何给定时间使用的内存就越少”,这里有更多的上下文,

第一遍中的数组可以容纳10兆字节或大约2^23字节的内存。由于数组中的每个元素都是int,而int是4个字节,因此我们最多可以容纳大约2^21个元素的数组。因此,我们可以推断出以下内容:

因此,我们可以得出以下结论:2^10

public class QuestionB {
    public static int bitsize = 1048576; // 2^20 bits (2^17 bytes)
    public static int blockNum = 4096; // 2^12
    public static byte[] bitfield = new byte[bitsize/8];
    public static int[] blocks = new int[blockNum];

    public static void findOpenNumber() throws FileNotFoundException {
        int starting = -1;
        Scanner in = new Scanner (new FileReader ("Chapter 10/Question10_3/input_file_q10_3.txt"));
        while (in.hasNextInt()) {
            int n = in.nextInt();
            blocks[n / (bitfield.length * 8)]++;
        }

        for (int i = 0; i < blocks.length; i++) {
            if (blocks[i] < bitfield.length * 8){
                /* if value < 2^20, then at least 1 number is missing in
                 * that section. */
                starting = i * bitfield.length * 8;
                break;
            }
        }

        in = new Scanner(new FileReader("Chapter 10/Question10_3/input_file_q10_3.txt"));
        while (in.hasNextInt()) {
            int n = in.nextInt();
            /* If the number is inside the block that’s missing 
             * numbers, we record it */
            if (n >= starting && n < starting + bitfield.length * 8) {
                bitfield [(n-starting) / 8] |= 1 << ((n - starting) % 8);
            }
        }

        for (int i = 0 ; i < bitfield.length; i++) {
            for (int j = 0; j < 8; j++) {
                /* Retrieves the individual bits of each byte. When 0 bit 
                 * is found, finds the corresponding value. */
                if ((bitfield[i] & (1 << j)) == 0) {
                    System.out.println(i * 8 + j + starting);
                    return;
                }
            }
        }       
    }

    public static void main(String[] args) throws FileNotFoundException {
        findOpenNumber();
    }

}

共有2个答案

皮嘉德
2023-03-14

我喜欢这个问题。我会再考虑一下,但我认为如果磁盘空间和时间不是问题,您可以将数字分成100k块,并在每个文件中对它们进行排序。任何没有100k条目的块都会有一个间隙。这一点也不优雅,但它会开始运作。

华涵意
2023-03-14

如果形成M个块,每个块的大小为2^32/M,则所需的总内存为M 2^27/M个字(32位)。当M=√2^27,位于1和2^27街区的中间。最小值为2^14.5个字,约92 KB。

这在双对数图上非常清楚。

 类似资料:
  • 问题内容: 我有一个表,带有2个重要列DocEntry,WebId 样本数据就像 现在我们可以在这里注意到,在WebId列中缺少S004。我们如何通过查询找到这些缺失的数字。 进一步说明: 如果网站ID之间缺少任何数字,则Web ID应按升序排列,例如S001,S002,S003,S004,S005。我没有任何单独的表格来输入可能的条目,因为这是不切实际的。我必须逐月查找丢失的数字,以每个月的开始

  • 问题内容: 给你一个包含 1 到 n 的整数数组,但数组中从 1 到 n 的数字之一丢失了。您需要提供最佳解决方案来找到丢失的数字。数组中的数字不能重复。 例如: 问题答案: 使用公式 n=n*(n+1)/2 求 n 个数字的总和 查找给定数组中存在的元素的总和。 减法(n 个数字的总和 - 数组中存在的元素的总和)。 查找数组中缺失数字的Java程序: 当你运行上面的程序时,你会得到以下输出:

  • 结果必须是:匹配0=6207匹配1=6204... 希望你能帮助我,谢谢。

  • 问题内容: 假设我们有两个连续的整数序列缺失,并且缺失的元素位于第一个元素与最后一个元素之间。我确实写了完成任务的代码。但是,我想尽可能地使用更少的循环来提高效率。任何帮助将不胜感激。当我们必须找到更多的缺失项(例如接近n / 4)而不是2时,情况又如何呢?我认为我的代码应该是高效的,因为我早先退出了循环? 问题答案: 假定L是没有重复的整数列表,则可以推断出,当且仅当且仅当且仅当且仅当且仅当且仅

  • 因此,我必须编写一个程序,使用numDigits方法找到一个范围内的所有回文数,该方法取一个int数并返回该数的位数,使用isPalindrome方法取一个int数并返回一个布尔值true或false。这是在爪哇。 我有一个numDigits方法编码,工作很好,但我不知道如何获得它的输出,并使用它找到一个范围内的所有回文 null

  • 问题内容: 我有一个从1到100(包括两端)的数字数组。数组的大小为100。将数字随机添加到数组中,但是数组中有一个随机的空插槽。找到该插槽的最快方法是什么,应该在插槽中放入多少?最好使用Java解决方案。 问题答案: 你可以在O(n)中执行此操作。遍历数组并计算所有数字的总和。现在,从1到N的自然数之和可以表示为。在你的情况下,N = 100。 从中减去数组的总和,其中N = 100。 那是丢失