【问题标题】:Why is a hash map get/set considered to have O(1) complexity?为什么哈希映射 get/set 被认为具有 O(1) 复杂性?
【发布时间】:2019-02-19 18:57:51
【问题描述】:

假设我们在 Javascript 中有以下哈希映射类:

class myHash {
    constructor() {
        this.list = [];
    }
    hash(input) {
        var checksum = 0;
        for (var i = 0; i < input.length; i++) {
            checksum += input.charCodeAt(i);
        }
        return checksum;
    }
    get(input) {
        return (this.list[this.hash(input)]);
    }
    set(input, value) {
        this.list[this.hash(input)] = value;
    }
}

hash 函数有一个复杂度为O(n) 的循环,并在 getter 和 setter 期间调用。这不会让哈希映射O(n)变得复杂吗?

【问题讨论】:

  • 什么是不使用 for 循环的更好的散列函数?{} 本身也被认为是 HashMap,不是吗?我正在尝试自己实现一个。
  • @Joshl 您的想法是正确的,但是您感到困惑的复杂性是完全不同的计算; 查找通常是常量,而散列函数不是。
  • @Joshl 通常当人们谈论数组或散列的复杂性时,他们谈论的是行为如何随着条目数量的变化而变化。在您的班级中,考虑当您有一个条目时get 需要多长时间,并将其与有一百万个条目时所需的时间进行比较。一个平均值它们将是相同的。

标签: javascript hashmap


【解决方案1】:

当您执行 Big-O 分析时,您需要非常清楚变量是什么。 n 通常是未定义或隐含的,但了解它到底是什么至关重要。

  • 让我们将 n 定义为哈希映射中的项目数。

n 是唯一考虑的变量时,所有方法都是O(1)。它们都没有在this.list 上循环,因此它们都以恒定时间相对于哈希映射中的项目数运行。

但是,你反对:hash() 中有一个循环。怎么可能是O(1)。好吧,它在循环什么?它是否在地图中的其他项目上循环?不。它在 input 上循环——但 input.length 不是我们正在考虑的变量。

当人们分析哈希图的性能时,他们通常会忽略传入的字符串的长度。如果我们这样做,那么 相对于 n 哈希图的性能是 O(1).


如果您确实关心字符串长度,那么您需要在分析中添加另一个变量。

  • 让我们将 n 定义为哈希映射中的项目数。
  • 让我们将 k 定义为正在读取/写入的字符串的长度。

散列函数是O(k),因为它以线性时间循环输入字符串。因此,get()set() 也是 O(k)。

为什么我们通常不关心k?为什么人们只谈论n?这是因为 k 是分析散列函数性能时的一个因素,但是当我们分析散列映射的执行情况时,我们并不真正关心散列函数的运行速度。我们想知道哈希映射本身的表现如何,并且它的代码都没有直接受到 k 的影响。只有hash() 是,hash() 不是哈希映射的一部分,它只是它的输入。

【讨论】:

    【解决方案2】:

    是的,字符串大小 (k) 确实很重要。 (更准确地说是哈希函数复杂度)


    假设:

    • 获取项目使用数组索引需要f(n)时间
    • 哈希函数需要g(k)时间

    那么复杂度是O( f(n)+g(k) )

    我们知道g(k)O(k),如果我们假设f(n)O(1),复杂度变成O(k)

    此外,如果我们假设字符串大小k 不会大于常量 c,则复杂度变为O(c),可以重写为@ 987654333@.


    所以事实上,鉴于您的实现,O(1) 仅在以下情况下才是正确绑定

    • 获取项目使用数组索引需要O(1)
    • 字符串不会长于常量c

    注意事项

    • 一些哈希函数本身可能是O(1),比如简单地取第一个字符或长度。
    • 应该检查get item use array index是否需要O(1),例如在javascript稀疏数组中可能需要更长的时间才能访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-11
      • 2019-12-24
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      • 2010-09-18
      相关资源
      最近更新 更多