如何确定HashMap中方法的最坏情况复杂度?

时间:2013-11-20 02:22:46

标签: java hashmap runtime time-complexity

public void addOccurence(String word) { 
    if (hm.containsKey(word)){
          hm.put(word, hm.get(word)+1);
    }
    else {hm.put(word, 1); }
}

我知道平均put(k,v)get(v)o(1),其最差的情况为o(n)。那么containsKey(v)呢? 以及如何确定以下内容的运行时间:

hm.put(word, hm.get(word)+1) 

最差情况是o(n^2),平均o(1)吗?

4 个答案:

答案 0 :(得分:1)

最糟糕的是 O(N)。你正在进行两次或三次操作,每次操作都是 O(N),,所以你有< em> 3N 仍然是 O(N)。你没有做任何二次性的事情。

答案 1 :(得分:1)

hm.put(word, hm.get(word)+1)的最差案例时间复杂度为O(N)

如何:假设您由于过度冲突而将hashMap转换为链接列表。因此get()必须搜索整个链表O(N)。类似地,hm.put()将需要遍历链表以插入值。所以O(N)+O(N) = O(2N) ~ = O(N)

即使对于插入,您也不会遍历整个链表,因此get()方法的时间复杂度为O(N)。所以总数是O(N)。因此,在这两种情况下,最坏情况的时间复杂度为O(N)

但同样的渐近下限为O(1)

如何: 因为如果您的密钥分布得很好,那么get()的时间复杂度会o(1)insert也会相同。因此导致渐近时间复杂度O(1)

答案 2 :(得分:1)

O(N)不是最坏的情况。 HashMap仅声称具有恒定的工作时间。事实上它不是真的。当特殊阈值超过时,通常通过重新划分Map来维持恒定的工作时间。看看内部HashMap方法:

void addEntry(int hash, K key, V value, int bucketIndex) {
    if ((size >= threshold) && (null != table[bucketIndex])) {
        resize(2 * table.length);
        hash = (null != key) ? hash(key) : 0;
        bucketIndex = indexFor(hash, table.length);
    }

    createEntry(hash, key, value, bucketIndex);
}

如果size大于阈值,则发生完全重新散列,其复杂性等于创建新的HashMap。所以最糟糕的情况是

  

O(新的HashMap(oldMap))+ O(N)

如果你重写了hashCode()函数,那么可能会发生O(N),因此它具有纯粹的分布。在默认实现中,这种情况无法实现。唯一的危险就是重新开始。

答案 3 :(得分:0)

最坏的情况运行时不是O(n^2),因为你没有每个循环都有O(n) RT的嵌套循环。运行时将是O(n),因为您要将hm.put(word, hm.get(word)+1)方法的RT从hm.containsKey(word)方法添加到RT。 O(n) + O(n) = O(2n) ==&gt; O(n)

最好的情况当然是如果字符串不在hashmap中并且else(...)语句已执行,或O(1)

public void addOccurence(String word) { 
    if (hm.containsKey(word)){ //Worst Case O(n)
        hm.put(word, hm.get(word)+1); //Worst case O(n)
    }
    else {hm.put(word, 1); }  //O(1) Runtime
}

作为旁注,containsKey(k)方法基本上是一个get(k)方法,它根据密钥是否存在返回一个布尔值。另一方面,假设密钥存在于hashmap中,get(k)方法实际上将返回密钥的值。两者的运行时间是相同的,因为它们基本上以相同的方式搜索hashmap。