问题 文件搜索索引的算法问题


有一个问题,我也有解决方案。但我无法理解解决方案。请帮助一些例子和淋浴一些经验。

给定一个包含大约3亿个社会安全号码(9位数字)的文件,找到一个不在文件中的9位数字。您拥有无限的驱动器空间,但只有2MB的RAM供您使用。

回答

在第一步中,我们构建一个初始化为0的数组2 ^ 16个整数,对于文件中的每个数字,我们将其16个最高有效位索引到此数组并递增数字。

由于文件中的数字少于2 ^ 32,因此数组中必须存在(至少)一个小于2 ^ 16的数字。这告诉我们在这些高位中可能的数字中至少缺少一个数字。

在第二遍中,我们只关注与该标准匹配的数字,并使用大小为2 ^ 16的位向量来识别缺失的数字之一。


1136
2018-05-28 21:59


起源



答案:


为了使解释更简单,假设你有一个两位数字的列表,其中每个数字在0到3之间,但你不能为16个可能的数字中的每个数字保留16位,无论你是否已经遇到了。你要做的是创建一个数组 a 4个3位整数和in a[i],你用第一个数字存储多少个数字 i 你遇到过(两位整数是不够的,因为你需要值0,4和它们之间的所有数字。)

如果你有这个文件

00,12,303,31,01,32,02

你的数组看起来像这样:

4,1,0,2

现在您知道所有以0开头的数字都在文件中,但是对于剩下的每个数字,至少有一个丢失。我们选择1.我们知道至少有一个以1开头的数字不在文件中。因此,创建一个4位的数组,对于每个以1开始的数字设置相应的位,最后选择一个未设置的位,在我们的示例中,如果可能为0.现在我们有了解决方案:10 。

在这种情况下,使用此方法是12位和16位之间的差异。使用您的数字,它是32 kB和119 MB之间的差异。


11
2018-05-28 22:31



谢谢svick ...这是最好的解释...... - AGeek
@svick很好地解释了......谢谢 - MoveFast
@svick,数组a上面是a [0] = 4 a [1] = 1 a [2] = 0 a [3] = 2因此,对于所有缺失的元素,我们将选择1-by-1并在文件中搜索如你所说。现在对于1,2和3位数字,我们将读取整个文件3次+ 1次(在beigning中),从优化的角度来看这是不好的。第二件事,我们如何得到确切的缺失数字尚不清楚,你对此有所了解,你的位数如何帮助解决这个问题。 - Hrishikesh Mishra


答案:


为了使解释更简单,假设你有一个两位数字的列表,其中每个数字在0到3之间,但你不能为16个可能的数字中的每个数字保留16位,无论你是否已经遇到了。你要做的是创建一个数组 a 4个3位整数和in a[i],你用第一个数字存储多少个数字 i 你遇到过(两位整数是不够的,因为你需要值0,4和它们之间的所有数字。)

如果你有这个文件

00,12,303,31,01,32,02

你的数组看起来像这样:

4,1,0,2

现在您知道所有以0开头的数字都在文件中,但是对于剩下的每个数字,至少有一个丢失。我们选择1.我们知道至少有一个以1开头的数字不在文件中。因此,创建一个4位的数组,对于每个以1开始的数字设置相应的位,最后选择一个未设置的位,在我们的示例中,如果可能为0.现在我们有了解决方案:10 。

在这种情况下,使用此方法是12位和16位之间的差异。使用您的数字,它是32 kB和119 MB之间的差异。


11
2018-05-28 22:31



谢谢svick ...这是最好的解释...... - AGeek
@svick很好地解释了......谢谢 - MoveFast
@svick,数组a上面是a [0] = 4 a [1] = 1 a [2] = 0 a [3] = 2因此,对于所有缺失的元素,我们将选择1-by-1并在文件中搜索如你所说。现在对于1,2和3位数字,我们将读取整个文件3次+ 1次(在beigning中),从优化的角度来看这是不好的。第二件事,我们如何得到确切的缺失数字尚不清楚,你对此有所了解,你的位数如何帮助解决这个问题。 - Hrishikesh Mishra


从圆形的角度来看,假设没有重复数据,则大约有1/3的数字存在于文件中。

我们的想法是对数据进行两次传递。将每个数字视为32位(无符号)数字。在第一遍中,记录在最重要的16位中有多少个数字具有相同的数字。在实践中,将存在许多代码,其中存在零(例如,所有那些用于10位SSN的代码;很可能,所有那些第一位数为零的代码也都丢失了)。但是在具有非零计数的范围中,大多数将不具有65536个条目,如果该范围中没有间隙,则将显示多少条目。所以,稍加注意,你可以选择其中一个范围集中在第二遍。

如果幸运的话,您可以在100,000,000..999,999,999中找到零项的范围 - 您可以选择该范围内的任何数字作为缺失。

假设你不是那么幸运,选择一个位数最少的一个(或任何一个小于65536个条目);称之为目标范围。将数组重置为全零。重读数据。如果您阅读的数字不在目标范围内,请忽略它。如果它在该范围内,则通过将数组的值设置为1来记录数字,以获得该数字的低16位。当您读取整个文件时,数组中带零的任何数字表示缺少SSN。


4
2018-05-28 22:31



很好的解释 - MoveFast