我在计算机科学课程中遇到了一个例子。
假设我们使用带链接的哈希并使用大小为m
的表。带有密钥k
的哈希函数映射记录到k mod m
个槽中。如果我们知道记录密钥是{i^2 | 1 <= i <= 100}
的子集,那么在最坏的情况下,m
搜索成本的值会更低?
a)11
b)7
c)9
d)12
我的TA说(1)是真的,但我认为这是假的。事实上,我不知道我们是如何得到这个!任何想法?
答案 0 :(得分:2)
您可以使用简单的代码凭经验检查:
int[] mVals = {11, 7, 9, 12};
for (int m : mVals) {
int[] cells = new int[m];
for (int i = 1; i<= 100; i++) {
int x = i*i % m;
cells[x]++;
}
System.out.println("m=" + m + " cells=" + Arrays.toString(cells));
}
将屈服:
m=11 cells=[9, 19, 0, 18, 18, 18, 0, 0, 0, 18, 0]
m=7 cells=[14, 29, 28, 0, 29, 0, 0]
m=9 cells=[33, 23, 0, 0, 22, 0, 0, 22, 0]
m=12 cells=[16, 33, 0, 0, 34, 0, 0, 0, 0, 17, 0, 0]
由于您的值在指定范围内,您可以看到m = 11表中的“最差”单元格中插入元素的概率为19/100
,而对于{的所有其他值, {1}} - 最高概率更高。
至于为什么,手头有几个因素:
m
的较大值 - 了解它,确保您了解当m
(所有元素都在一个列表中)或m=1
时发生的事情(一半)两个列表中的每一个中的元素)答案 1 :(得分:1)
作为一般的经验法则,您通常希望在散列中使用大质数来进行模数化,因为它会生成更多不同的值,并且这些值会导致散列表的插槽中的分布更均匀。由于11
是您列表中最大的素数,因此直观地认为它是最好的。
对于您的特定问题,我们有记录:
1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, ..., 10000
对于您的每个选项,我们必须找到此集合中有多少不同的值生成模数您的变体。
11
:
if n mod 11 = 0 => n*n mod 11 = 0
if n mod 11 = 1 => n*n mod 11 = 1 (1)
if n mod 11 = 2 => n*n mod 11 = 4 (2)
= 3 = 9 (3)
= 4 = 5 (4)
= 5 = 3 (5)
= 6 = 3
= 7 = 5
= 8 = 9
= 9 = 4
= 10 = 1
7
:
if n mod 7 = 0 => n*n mod 7 = 0 (1)
= 1 = 1 (2)
= 2 = 4 (3)
= 3 = 2 (4)
= 4 = 2
= 5 = 4
= 6 = 1
9
:
if n mod 9 = 0 => n*n mod 9 = 0 (1)
= 1 = 1 (2)
= 2 = 4 (3)
= 3 = 0
= 4 = 7 (4)
= 5 = 7
= 6 = 0
= 7 = 4
= 8 = 1
同样适用于12
。正如您所看到的,11
是为方块生成更多不同值的方法,因此它会在哈希表格的箱子中更均匀地分布您的值。在最坏的情况下,更均匀的传播可以降低搜索成本。