【发布时间】:2012-06-23 02:14:29
【问题描述】:
我正在阅读这个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 的答案以获得或多或少的 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;
}
【问题讨论】:
-
我认为对于“一种更快(在极限内)的方式”,作者打错字并打算写
O(n*log(n)),这就是你从例如得到的。由平衡二叉搜索树支持的集合。很明显,没有比O(n)更快的方法了。 -
我没有得到 log(n) 部分。
-
在平衡的 BST 中,插入和查找是
O(log(size)),所以如果你执行n查找和插入,你就有O(n*log n)操作。我想这就是日志的来源。 -
如果你看到下面的答案,作者说它是 O(n) 但你说它是 O(nlog(n))。我无法确定哪个是正确的。你能看到答案吗?
-
这取决于使用的集合类型的实现。对于使用平衡 BST 实现的集合,它是
O(n*log n)。对于 HashSet,如果 HashSet 保持O(1)插入和查找承诺,则为O(n)。 (对于 HashSet 的错误实现,它可能会降级为O(n^2),但我很乐观地认为java.util.HashSet不会。)我的猜测是链接问题的答案的作者认为 i> 首先是树集并将O(n*log n)拼写为O(log n),后来决定使用HashSet,忘记更改复杂性。或者最初具有正确的复杂性并被错误纠正。
标签: algorithm time time-complexity duplicate-removal