为什么以下两个重复的查找器算法具有不同的时间复杂度?

时间:2012-06-23 02:14:30

标签: algorithm time time-complexity duplicate-removal

我正在阅读question。所选答案包含以下两种算法。我无法理解为什么第一个时间复杂度为O(ln(n))。在最坏的情况下,如果数组不包含任何重复项,它将循环n次,第二次循环也是如此。我错了还是错过了什么?谢谢

1)更快(极限)的方式

这是一种基于哈希的方法。你必须为自动装箱付费,但它是O(ln(n))而不是O(n2)。一个有进取心的灵魂会找到一个原始的基于int的哈希集(Apache或Google Collections有这样的东西,可以解决这个问题。)

boolean duplicates(final int[] zipcodelist)
{
  Set<Integer> lump = new HashSet<Integer>();
  for (int i : zipcodelist)
  {
    if (lump.contains(i)) return true;
    lump.add(i);
  }
  return false;
}

2)向HuyLe鞠躬

请参阅HuyLe对或多或少O(n)解决方案的回答,我认为这需要一些额外的步骤:

static boolean duplicates(final int[] zipcodelist) {    
    final int MAXZIP = 99999;    
    boolean[] bitmap = new boolean[MAXZIP+1];    
    java.util.Arrays.fill(bitmap, false);    

    for (int item : zipcodeList)
        if (!bitmap[item]) bitmap[item] = true;
        else return true;    
    }

    return false; 
}

1 个答案:

答案 0 :(得分:2)

第一个解决方案应该具有预期的O(n)复杂度,因为必须遍历整个邮政编码列表,并且处理每个邮政编码是O(1)预期的时间复杂度。

即使考虑到插入HashMap可能会触发重新哈希,复杂性仍然是O(1)。这有点不合理,因为Java HashMap与链接中的假设之间可能没有任何关系,但它可以证明它是可能的。

来自HashSet文档:

  

此类为基本操作提供常量时间性能(添加,删除,包含和大小),假设哈希函数在桶之间正确地分散元素

对于正确分析的第二种解决方案是相同的:O(n)。

(只是一个偏离主题的注释,BitSet比数组更快,如原始帖子所示,因为8 boolean被打包到1 byte中,它使用更少的内存。)