哈希表时间复杂度混乱

问题描述

我刚刚开始学习哈希字典。当前,我们正在实现一个哈希字典,该字典具有由链(链接列表)组成的单独存储桶。这本书提出了这个问题,我很难弄清楚这个问题。假设我们的初始表大小为10,即10个存储桶。如果我们想知道n次插入和一次查找的时间复杂度,我们如何解决呢? (假设指针访问是一个时间单位)。

它提出了三种情况:

  1. 不调整大小的哈希字典,n次插入和1次查找的时间复杂度是多少?
  2. 一个哈希字典,当负载因子超过.8时,其大小将调整为1,n次插入和1次查找的时间复杂度是多少?
  3. 一个哈希字典,当负载因子超过.8时,它通过将表大小加倍来调整大小,那么n次插入和1次查找的时间复杂度是多少?

我最初的想法使我感到非常困惑。我不太清楚如何知道某个给定插入链的长度。假设k个长度(我认为),for循环的指针访问会遍历整个链,因此有k个时间单位。然后,在每次插入的迭代中,它都会检查当前节点的数据是否等效于尝试插入的密钥(如果存在,则将其覆盖),因此,如果找不到,则为2k单位时间,如果找到,则为2k + 1。然后,它进行5次指针访问以添加某些元素。因此,2k + 5或2k + 1插入1次。因此,对于第n个插入情况,第一个方案的O(kn)。为了查找,它似乎是2k + 1或2k。因此,对于1次查找,o(k)。我不知道如何处理其他两种情况。一些帮助将是巨大的。再次澄清:问题中未提及k。给出的唯一事实是初始大小为10以及方案中给出的信息,因此k不能用作n次插入或1次查找的时间复杂性的结果。

解决方法

如果您具有哈希字典,那么在最坏的情况下,插入,删除和搜索操作将花费O(n)的时间复杂度为1个键。对于n次插入,它将为O(n^2)。表格的大小无关紧要。

|--------|
|element1| -> element2 -> element3 -> element4 -> element5
|--------|
|  null  |
|--------|
|  null  |
|--------|
|  null  |
|--------|
|  null  |
|--------|
  • 现在平均情况下
  1. 方案1的负载因子固定(假设m个插槽):n/m。因此,一个插入函数将是O(1+n/m)。 1用于哈希函数计算,n / m用于查找。
  2. 对于第二种情况和第三种情况,应分别为O(1+n/m+1)O(1+n/2m)

让您感到困惑的是,您可以问自己一个问题,即任意随机密钥集的预期链长是多少。解决的办法是我们不能完全确定。 在那里,用负载因子的概念来定义平均情况,如果没有,我们给每个插槽相等的概率来形成一条链。键数大于插槽数。

,

想象一下,我们的初始表大小为10,即10个存储桶。如果我们想知道n次插入和一次查找的时间复杂度,我们如何解决呢?

当我们谈论时间复杂性时,我们正在研究n接近无穷大时n-vs-for-time-for-time曲线的陡度。在上面的例子中,您说的是只有十个存储桶,因此-假设哈希函数以近似均一的分布(如其应有的那样)将存储桶中的插入分散在各个存储桶中,则n个插入将产生10个大约n / 10的列表元素。

在每次插入期间,您都可以在O(1)时间内将其哈希到正确的存储桶。现在-这里的关键因素是您是否希望哈希表实现保护您避免重复插入。

  • 如果您只是简单地相信不会有重复项,或者允许哈希表具有重复项(例如C ++的unordered_multiset),则可以在不检查现有存储桶内容的情况下完成插入本身桶列表的可访问末端(即使用头或尾指针),也以O(1)时间表示。这意味着每次插入的总时间为O(1),n次插入的总时间为O(n)。

  • 如果实现可以识别并避免重复,则对于每个插入,它都必须沿着现有的链表进行搜索,链表的大小与n相关的常数为#buckets因子(1/10),并且有所不同从元素的最终数量的1到1/10线性插入,因此平均为n / 2/10,这将除去常数因子简化为n。换句话说,每次插入都是O(n)。

大概该问题旨在询问在插入所有元素之后进行一次查找的时间:在这种情况下,您有10个链接列表,每个列表的长度约为n / 10,因此查找将散列到其中一个列表,然后平均而言,在找到所需的值之前,必须先遍历列表的一半:大约搜索了n / 20个元素,但由于/ 20是一个恒定因子,因此可以将其删除,我们可以说平均复杂度为O(n)。

不调整大小的哈希字典,n次插入和1次查找的时间复杂度是多少?

好吧,我们在上面讨论了哈希表大小为10的问题。

一个哈希字典,当负载因子超过.8时将其大小调整为1,n次插入和1次查找的时间复杂度是多少?

假设表格有100个存储桶和80个元素,请插入第81个元素,将其大小调整为101,然后负载系数约为.802-是否应该立即重新调整大小,还是等到下一次插入?无论如何,忽略-each调整大小操作涉及到访问,重新哈希处理(除非元素或节点缓存哈希值),以及“重新编写”所有现有元素的链接列表:即O(s),其中s是表中的大小那个时间点。并且您对s值从1到n进行了一次或两次(取决于您对上述“立即重新调整大小”行为的回答),因此s的平均值为n / 2,从而简化为n。插入本身可能会或可能不会涉及存储桶的链表的另一次迭代(您可以在调整大小时进行优化搜索)。无论总体时间复杂度是O(n 2 )。

然后查找使用O(1),因为调整大小使负载因子保持在恒定值以下(即,平均链表长度非常非常短(甚至忽略了空的存储桶)。

一个哈希字典,当负载因子超过.8时,它通过将表大小加倍来调整大小,那么n次插入和1次查找的时间复杂度是多少?

如果您考虑在其中插入了n个元素的结果哈希表,那么大约一半的元素将被插入而无需重新哈希,而大约四分之一的元素将被重新哈希一次,而八个将被重新哈希两次,第十六次刷新了3次,第32次刷新了4次:如果您将该系列总结为-1/4 + 2/8 + 3/16 + 4/32 + 5/64 + 6/128 ...-该系列接近1当n达到无穷大时。换句话说,最终表大小中每个元素的平均重复哈希/链接工作的平均数量不会随n的增加而增加-它是恒定的。因此,总插入时间仅为O(n)。然后,由于负载因子保持在0.8以下(常数而不是n的函数),因此查找时间为O(1)。