我正在尝试实现平面扫描算法,为此我需要知道java.util.HashMap class' keySet()方法的时间复杂度。我怀疑它是O(n log n)。我是对的吗?
澄清点:我在谈论keySet()方法的时间复杂性;迭代返回的Set将明显花费O(n)时间。
答案 0 :(得分:15)
实际上,获取密钥集是O(1)
并且便宜。这是因为HashMap.keyset()返回与HashMap关联的实际KeySet对象。
返回的Set 不是键的副本,而是实际HashMap状态的包装器。实际上,如果你更新集合,你实际上可以改变HashMap的状态;例如在集合上调用clear()
将清除HashMap!
答案 1 :(得分:5)
肯定会是O(1)。它正在做的就是在HashMap上返回一个包装器对象。
如果你在谈论遍历键集,那么这是O(n),因为每个next()调用都是O(1),这需要执行n次。
答案 2 :(得分:2)
这应该在O(n)时间内可行...哈希映射通常实现为大型桶阵列,桶的大小(通常)与哈希映射的大小成正比。为了检索密钥集,必须迭代桶,并且对于每个集合项,必须检索密钥(通过中间集合或直接访问存储桶的迭代器)...
**编辑:正如其他人所指出的那样,实际的keyset()方法将在O(1)时间内运行,但是,迭代密钥集或将其转移到专用集合将是O(n)操作。不太确定你要找哪一个**
答案 3 :(得分:0)
Java集合有很大的空间,因此不需要花费太多时间。我认为,这种方法是O(1)。这个系列只是坐在那里。
答案 4 :(得分:0)
要解决“迭代返回的Set显然需要O(n)时间”的注释,根据HashMap
的{{3}},这实际上是不正确的:
在集合视图上进行迭代需要的时间与HashMap实例的“容量”(存储桶数)及其大小(键值映射数)成正比。因此,如果迭代性能很重要,那么不要将初始容量设置得太高(或负载因子太低)是非常重要的。
因此,换句话说,对返回的Set
进行迭代将花费O(n + c)
,其中n
是地图的大小,c
是地图的容量,而不是{{1 }}。如果选择了不合适的初始容量或负载因子,则O(n)
的值可能会超出迭代时间的地图实际大小。
答案 5 :(得分:0)
切线答案:
...遍历返回的
Set
显然将花费O(n)
时间。
实际上并非总是 正确:
使用HashMap
创建new HashMap<>()
确实如此。最坏的情况是让所有N
键都位于同一哈希链中。但是,如果地图自然增长,则哈希数组中仍将有N
个条目和O(N)
个时隙。因此,迭代条目集将涉及O(N)
个操作。
如果HashMap
是用new HashMap<>(capacity)
创建的,并且估计值为capacity
奇异(太大),则为假。然后,将需要O(Cap) + O(N)
个操作来迭代条目集。如果我们将Cap
视为变量,即O(max(Cap, N))
,可能会比O(N)
差。
尽管有一个转义子句。由于capacity
是当前int
API中的HashMap
,因此Cap
的上限是2 31 。因此,对于真正的大Cap
和N
而言,复杂度为O(N)
。
另一方面,N
受可用内存量的限制,实际上,{{1},您需要按2 38 字节(256GBytes)顺序排列的堆}超过可能的最大N
值。对于如此大小的地图,最好使用针对大型地图调整的哈希表实现。还是不使用过大的容量估算值!