从集合构造 PriorityQueue 的时间复杂度是多少?
What is the time complexity of constructing a PriorityQueue from a collection?
Java 的 PriorityQueue 构造函数与 Collection
的复杂性如何?
我使用了构造函数:
PriorityQueue(Collection<? extends E> c)
复杂度是O(n)还是O(n*log(n))?
从集合(即使是未排序的集合)中初始化 PriorityQueue
的时间复杂度为 O(n)。这在内部使用一个名为 siftDown()
的过程到 "heapify" 数组 in-place。 (这在文献中也被称为下推。)
这是违反直觉的。将一个元素插入堆中似乎是 O(log n),因此插入 n 个元素会导致 O(n log n) 复杂度。如果您一次插入一个元素,就会出现这种情况。 (在内部,插入单个元素使用 siftUp()
执行此操作。)
堆化一个单独的元素当然是O(log n),但是siftDown()
的"trick"是在处理每个元素时,它必须筛选过去的元素数量是不断减少。所以总复杂度不是 n 个元素乘以 log(n);它是筛选剩余元素的递减成本的 n 项之和。
请参阅 this answer, and see also this article 通过数学计算得出的结果。
Java 的 PriorityQueue 构造函数与 Collection
的复杂性如何?
我使用了构造函数:
PriorityQueue(Collection<? extends E> c)
复杂度是O(n)还是O(n*log(n))?
从集合(即使是未排序的集合)中初始化 PriorityQueue
的时间复杂度为 O(n)。这在内部使用一个名为 siftDown()
的过程到 "heapify" 数组 in-place。 (这在文献中也被称为下推。)
这是违反直觉的。将一个元素插入堆中似乎是 O(log n),因此插入 n 个元素会导致 O(n log n) 复杂度。如果您一次插入一个元素,就会出现这种情况。 (在内部,插入单个元素使用 siftUp()
执行此操作。)
堆化一个单独的元素当然是O(log n),但是siftDown()
的"trick"是在处理每个元素时,它必须筛选过去的元素数量是不断减少。所以总复杂度不是 n 个元素乘以 log(n);它是筛选剩余元素的递减成本的 n 项之和。
请参阅 this answer, and see also this article 通过数学计算得出的结果。