java - 使用有限的内存查找丢失的号码

标签 java algorithm

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

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

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

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

enter image description here

因此,我们可以得出以下结论: 2^10< rangeSize <2^26,这些条件给了我们很大的“Swing 空间”,但我们选择的越接近中间,在任何给定时间使用的内存就越少。

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();
    }

}

最佳答案

如果您形成 M 个 block ,每个 block 的大小为 2^32/M,则所需的总内存为 M+2^27/M 字(32 位)。当 M=√2^27,即 1 和 2^27 block 之间的一半时,该函数达到最小值。最小为 2^14.5 字,约 92 KBytes。

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

enter image description here

关于java - 使用有限的内存查找丢失的号码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34096760/

相关文章:

algorithm - group-by 似乎改变了范围的顺序

c# - 从许多多边形的并集构造多边形

javascript - 扁平化/取消扁平化嵌套 JavaScript 对象的最快方法

c++ - 最长公共(public)子序列长度函数没有返回正确的长度?

java - java中的二维数组列表和类继承

java - 使用另一个类创建新对象

java - 如何将图像上传到 Android Studio 中的图像 slider ?

algorithm - 从给定的节点度构造一个图

java - 如何在 java 中组合具有相同属性值的对象的 2 个数组列表

java - 我的用于输入姓名、年龄以及查看一个人是否年龄足以做某事的 Java 代码有什么问题?