我有两个未分类的32位无符号整数数组,大小分别为N1和N2。每个数组可能包含重复项。我想将每个值(2 ^ 32个可能的键)映射到大小为(N1 + N2)的字节数组中的一个点,以记录每个键的频率。重复的键值应映射到此数组中的相同位置。另外,每个整数的频率不会超过100(这就是为什么我选择一个字节数组来记录每个键的频率以节省空间);如果最大可能频率高于此值,我只需将字节数组更改为短路或其他数组。
最后,我需要一个大小为N1 + N2的数组 - 不一定会使用所有条目,因为可能遇到了重复项 - 每个唯一键值的频率。在最坏情况下,将仅使用一个字节条目(例如,两个阵列中的所有值都相同),留下((N1 + N2)-1)条目未使用。在最佳情况下,使用所有字节条目。
根据我的理解,我需要找到最小完美散列函数来映射已知数量的未知键(N1 + N2) ;所有范围从0 - 2 ^ 32)到已知点数(N1 + N2)。我能找到一些其他帖子,但两个答案基本上都说使用gperf:
Is it possible to make a minimal perfect hash function in this situation?
第二个(Minimal perfect hash function)正是我试图做的。
而不是期待答案的源代码(我顺便使用C),我更喜欢解释如何为N创建最小完美散列函数N桶的任何可能正整数的数量。对于每个可能存在大量未使用空间的整数,我可以轻松地使用4 GB直接映射数组,但我宁愿尝试减少这种巨大的空间效率。我也希望不使用任何外部库,主要是出于教育目的,以了解有关哈希本身的更多信息。
答案 0 :(得分:1)
这显然是不可能的。如果你有N个数字,那么除非你事先知道这些数字是什么,否则无法找到一个将它们全部散列到[0,N]范围内的不同值的函数。否则,给定任何这样的函数(当然, N < 2 ^ 32),将至少有一对整数,使得这两个整数都散列到相同的值,因此该函数如果这些整数都出现在输入中,那将是不完美的。
如果你放松了允许动态创建函数的条件,这就成了可能,但只能以一种非常简单和无用的方式。也就是说,哈希函数可以通过记录每个输入到它的数字并为每个数字生成一个新的唯一输出(比如从0开始计数)来构建自己。但是这样的函数需要一个哈希表(或类似的东西)作为其实现的一部分,所以它在实现哈希表中肯定没有用!
答案 1 :(得分:0)
根据Pigeonhole Principle,您将拥有由多个号码占用的“哈希位置”。换句话说:不同的数字将“哈希”到相同的值。
现在,我想知道你是否可以从Bloom Filter中受益。来自维基百科:
可能存在误报,但假阴性不是;即 查询返回“可能在集合中”或“绝对不在集合中”。
如果某些东西“肯定”不在该组键中,您可以继续(其频率为1),如果它可能在该组中,则进一步处理以累积其实际统计量。