我正在阅读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;
}
答案 0 :(得分:2)
第一个解决方案应该具有预期的O(n)复杂度,因为必须遍历整个邮政编码列表,并且处理每个邮政编码是O(1)预期的时间复杂度。
即使考虑到插入HashMap可能会触发重新哈希,复杂性仍然是O(1)。这有点不合理,因为Java HashMap与链接中的假设之间可能没有任何关系,但它可以证明它是可能的。
来自HashSet文档:
此类为基本操作提供常量时间性能(添加,删除,包含和大小),假设哈希函数在桶之间正确地分散元素。
对于正确分析的第二种解决方案是相同的:O(n)。
(只是一个偏离主题的注释,BitSet比数组更快,如原始帖子所示,因为8 boolean
被打包到1 byte
中,它使用更少的内存。)