我必须从数组(在下面的代码中称为int indexes[] = { 0, 1, 2, 3 };
// sort indexes <== YOUR TASK
// indexes now is { 1, 0, 2, 3 }
for (i = 0; i < 4; i++) {
printf("%f for %s\n", year2010Cases[indexes[i]], caseName[indexes[i]]);
}
)中构造一个最大堆,因此我正在使用nums
。
我的代码如下:
java.util.PriorityQueue
我正在尝试查找上述PriorityQueue<Integer> pq = new PriorityQueue<>(nums.length, (a, b) -> b - a);
for (int i = 0; i < nums.length; i++) {
pq.offer(nums[i]);
}
循环的时间复杂度(以Big-O表示)。
我知道for
没有指定底层数据结构增长的详细信息。 (在最坏的情况下,扩展内部数组并在新分配的空间上复制所有元素时,它可能是PriorityQueue
。
但是我假设当我指定O(n)
并且添加的元素不超过此initialCapacity
时,上述循环的最坏情况下的时间复杂度应该是initialCapacity
而不是O(n)
。从here我了解到,堆的构建时间为O(nlog(n))
,而O(n)
是一个宽松的上限。
我是正确的,还是我缺少什么?
我只是想了解,如果我将nlog(n)
中的PriorityQueue
配置为initialCapacity
并在该优先级队列中添加n
元素,那么时间的复杂度是多少这个建筑堆的过程?
PS:我已经看过this,但是针对该问题的答案只是声称没有解释,可能不是Java特有的。
我还看到n
具有一个接受java.util.PriorityQueue
的构造函数。这将是该构造的时间复杂度?应该不是Collection
吗?
答案 0 :(得分:2)
我知道
PriorityQueue
没有指定底层数据结构增长的详细信息。
让我们对此清楚。 Javadoc 声明,未指定用于扩展队列的策略。
(在最坏的情况下,扩展内部数组并在新分配的空间上复制所有元素时,它可能是O(n)。
当前政策(Java 11)为:
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
对于“双重”保单,每次插入的摊销成本为O(1)。对于增长50%是没有那么好。但比O(n)的方式更好。
可以肯定地说,不管当前的规范(技术上)允许什么,他们都不会单方面将此政策更改为复杂性大大恶化的事情。
但是,这与您的问题没有关系,因为您正在使用initialCapacity
容量,无论是显式使用还是从集合中填充PriorityQueue
。
我假设当我指定
initialCapacity
且添加的元素不超过此`initialCapacity'时,以上循环的最坏情况下的时间复杂度应为O(n)而不是O(nlog(n ))。我从这里了解到,堆的构建时间为O(n),nlog(n)是一个宽松的上限。我是正确的,还是我缺少什么?
我认为您缺少某些东西。
假定您的输入数组未排序,则按顺序构建堆(“堆”)并按顺序检索元素等效于将元素按优先级排序。平均而言,这是一个O(nlogn)操作。虽然堆化本身为O(n)(因为代码使用向下堆化),但实际上您已经推迟了一些排序成本,直到以后。
因此,除非您只打算检索放入队列中的元素的非O(n)子集,否则总的答案是O(nlogn)。
我只是想了解,如果我将
PriorityQueue
中的initialCapacity
配置为n
并在该优先级队列中添加n
元素,那么时间的复杂度是多少这个建筑堆的过程?
由于上述原因,总体复杂度(添加和删除n个元素)将为O(nlogn)。
我还看到
PriorityQueue
有一个接受Collection的构造函数。这将是该构造的时间复杂度?应该不是O(n)吗?
如果集合是未排序的,那么元件必须heapified;往上看。有一些特殊情况下的代码可以处理SortedCollection
,从而跳过了堆积步骤。
注意:
PriorityQueue
的源代码来确认上面的详细信息。谷歌可以帮您找到它。(a, b) -> b - a
不适用于整数排序,除非它们为正数。