【问题标题】:Time Complexity of Java PriorityQueue (heap) insertion of n elements? [duplicate]Java PriorityQueue(堆)插入n个元素的时间复杂度? [复制]
【发布时间】:2018-05-05 08:41:02
【问题描述】:

我想知道PriorityQueue.Add() 的Java n 元素的时间复杂度是多少。

我知道插入单个元素的潜在更坏情况是O(log(n)),但我不清楚插入n 元素集合的时间复杂度是多少?

我已经看到来自各种来源(没有证据)的声明,即构建 n 元素的优先级队列堆的时间是 O(n),并且还看到声称它是 O(nlog(n)),这使得给定插入的感觉是O(log(n)),乘以n 确实等于O(nlog(n))

注意:我只对更坏的情况感兴趣,而不是摊销。

这个问题假设有一种合乎逻辑的方式来描述使用 n 元素填充数据结构(堆)的行为,这与单独考虑 n x log(n) 插入不同。

我没有对输入做任何假设(例如输入值集的界限,或部分有序的输入)。

【问题讨论】:

  • 下面的人在玩你错误的定义。插入数据结构的时间复杂度通常意味着如果结构中有 n 个元素,那么向其中插入 1 个元素的时间复杂度是多少。你说插入n个元素。如果要插入 n,则不能插入小于 n。
  • @MarianP 没有标准的逻辑方式来描述用n 元素“填充”数据结构的行为吗?这是一种相当常见的情况。
  • @pjs 是的,你是对的,这是重复的。我将投票结束并指出​​现有问题

标签: java time-complexity heap priority-queue


【解决方案1】:

看来n个元素的插入应该是O(n log n)

Java PriorityQueue (Java Doc)

入队和出队方法(offer、poll、 删除()并添加)

对于 remove(Object) 和 contains(Object) 方法的 O(n)

检索方法(peek、元素和大小)的 O(1)

这些时间复杂度似乎都是最坏的情况 (wiki),.add() 除外。正如 Java Doc 对这种未绑定结构的扩展所指出的那样,您对边界提出质疑是正确的:

增长政策的细节没有具体说明

正如他们在 Doc 中所述,PriorityQueue 基于具有特定初始容量的数组。我会假设增长将花费 O(n) 时间,这也是 .add() 的最坏情况时间复杂度。

要保证添加 n 个元素的 O(n log n) 时间,您可以声明 n 个元素的大小以省略容器的扩展:

PriorityQueue(int initialCapacity)

编辑: 对于 O(n) 构造时间的说法是正确的(如 cmets 中的@pjs 所述)。这个过程通常被称为heapify,它作用于一个预先存在的数组,该数组用于在 O(n) 时间内在其上构造一棵二叉树。

【讨论】:

  • 抱歉,但是您的直觉(因此您的答案)对于构建堆是错误的。我已将此标记为重复,您可以在此处找到正确答案以及指向来源和证明的多个链接。
  • 感谢您的反馈,我修改了答案的那一部分。我不认为这是重复的,因为问题与特定 Java 容器的 .add() 方法有关,而不是与一般堆的构造有关。
【解决方案2】:

一般情况下是O(N log N)O(N) 算法适用于输入已经排序的特殊情况,但java.util.PriorityQueue 中没有提供。

【讨论】:

  • 有趣的是,假设输入是特定类型,还有更精细的方法可以在线性时间进行排序,这篇文章中提到了一些:stackoverflow.com/questions/749585/sorting-in-linear-time
  • @gue 哦,是的。例如,如果输入的 PQ 顺序已经正确,则它只是 pq.a[i++] = input.nextElement()
  • 不需要预先排序的数据,有一个适用于任何数据集的 Theta(n) 算法。请参阅链接的答案。
  • 怎么样:log 1, log 2... log N 用于插入第 1, 2, .... N 个元素?日志 1 + 日志 2 + ... + 日志 N = 日志 N!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-19
  • 1970-01-01
  • 2011-09-01
  • 2020-04-17
  • 2022-01-20
  • 2021-03-13
  • 2022-01-22
相关资源
最近更新 更多