Java中使用PriorityQueue的第k个最小数字的时间复杂度
Posted
技术标签:
【中文标题】Java中使用PriorityQueue的第k个最小数字的时间复杂度【英文标题】:Time complexity of k-th smallest number using PriorityQueue in Java 【发布时间】:2019-03-15 19:37:32 【问题描述】:我正在尝试解决流行的面试问题Find the k-th smallest number in an array of distinct integers
。我看了一些解决方案,发现堆数据结构非常适合这个问题。
因此,我尝试使用 Collections 框架的PriorityQueue
类来实现一个解决方案,假设它在功能上与堆相同。
这是我尝试过的代码:
public static int getKthMinimum(int[] input, int k)
PriorityQueue<Integer> heap = new PriorityQueue<Integer>();
// Total cost of building the heap - O(n) or O(n log n) ?
for(int num : input)
heap.add(num); // Add to heap - O(log n)
// Total cost of removing k smallest elements - O(k log n) < O(n) ?
while(k > 0)
heap.poll(); // Remove min - O(log n)
k--;
return heap.peek(); // Fetch root - O(1)
基于docs,poll 和 add 方法需要 O(log n) 时间,而 peek 需要恒定时间。
while
循环的时间复杂度是多少? (我认为 O(k log n))。
就本问题而言,是否应将 O(k log n) 视为高于 O(n)?是否有切换的阈值?
这段代码的总时间复杂度是多少?会是 O(n) 吗?
如果还不是 O(n),有没有办法在 O(n) 中解决它,同时使用 PriorityQueue 类?
【问题讨论】:
【参考方案1】:1。
while
循环的时间复杂度是多少? (我认为 O(k log n))。
O(k log n) 是正确的。
2。出于这个问题的目的,是否应该将 O(k log n) 视为高于 O(n)?有没有切换的门槛?
你不能这样假设。 k 可以是 0 到 n-1 之间的任意值,这意味着 k log n 可以是 0 之间的任意值到 n 记录 n。
3。这段代码的总时间复杂度是多少?会是O(n)吗?
O(n log n),因为这是构建堆的成本。
可以在 O(n) 时间内构建一个堆,但您的代码不会这样做;如果是这样,那么您的总复杂度将是 O(n + k log n) 或者,等效地,O(MAX(n, k log n))。
4。如果还不是 O(n),有没有办法在 O(n) 中解决它,同时使用 PriorityQueue 类?
没有。在最坏情况O(n) 时间存在selection algorithms,但它们有点复杂,它们不使用PriorityQueue
。
最快的基于PriorityQueue
的解决方案需要 O(MAX(n, n log MIN(k em>, n-k))) 时间。 (关键是在迭代时只保留堆中 k 个最小的元素——或者 n-k 个最大的元素并使用 max-堆,如果 k 足够大,值得这样做。)
【讨论】:
以上是关于Java中使用PriorityQueue的第k个最小数字的时间复杂度的主要内容,如果未能解决你的问题,请参考以下文章
背包专题A - Bone Collector II hdu2639 01背包的第k个最优解
java - 如何使用PriorityQueue集合从Java中的给定数组在O(n)时间内构建最大堆?
LeetCode 378. 有序矩阵中第K小的元素 Java