使用Java中的PriorityQueue的第k个最小数的时间复杂度

时间:2019-03-15 19:37:33

标签: java algorithm collections time-complexity priority-queue

我正在尝试解决广受欢迎的面试问题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花费恒定时间。

  1. while循环的时间复杂度是多少? (我认为O(k log n))。
  2. 出于这个问题的目的,应认为O(k log n)高于O(n)吗?是否有切换的阈值?
  3. 此代码的总时间复杂度是多少?会是O(n)吗?
  4. 如果还没有O(n),有没有办法在使用PriorityQueue类的情况下在O(n)中解决它?

1 个答案:

答案 0 :(得分: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 )或等效地是< em> O (MAX( n k log n ))。

  

4。如果尚未使用O(n),是否可以使用PriorityQueue类在O(n)中进行求解?

不。在最坏的情况下,存在selection algorithms时间是 O n ),但是它们有点复杂,并且不使用PriorityQueue

最快的基于PriorityQueue的解决方案需要 O (MAX( n n log MIN( k n - k )))时间。 (关键是在迭代时仅将 k 个最小的元素保留在堆中,或者将 n - k 个最大元素并使用max-如果 k 足够大,那么就值得了。)

相关问题