{Java-PriorityQueue}此代码的时间复杂度

Pet*_*ter 3 java algorithm priority-queue time-complexity comparator

给定一个包含N个点的数组,找到2D平面中最接近原点(0,0)的K个点。您可以假设K比N小得多,并且N非常大。

例如:

    given array: (1,0), (3,0), (2,0), K = 2 
        Result = (1,0), (2,0)  
Run Code Online (Sandbox Code Playgroud)

(结果应按距离升序排列)

码:

import java.util.*;

class CPoint {
    double x;
    double y;
    public CPoint(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

public class KClosest {
    /**
     * @param myList: a list of myList
     * @param k: the number of closest myList
     * @return: the k closest myList
     */
    public static CPoint[] getKNearestPoints(CPoint[] myList, int k) {

        if (k <= 0 || k > myList.length)  return new CPoint[]{};                                
        if (myList == null || myList.length == 0 )  return myList; 

        final CPoint o = new CPoint(0, 0); // origin point

        // use a Max-Heap of size k for maintaining K closest points
        PriorityQueue<CPoint> pq = new PriorityQueue<CPoint> (k, new Comparator<CPoint> () {
            @Override
            public int compare(CPoint a, CPoint b) {
                return Double.compare(distance(b, o), distance(a, o));  
            }
        });

        for (CPoint p : myList) {   // Line 33
            // Keep adding the distance value until heap is full. // Line 34
            pq.offer(p);            // Line 35
            // If it is full        // Line 36
            if (pq.size() > k) {    // Line 37
                // Then remove the first element having the largest distance in PQ.// Line 38
                pq.poll();          // Line 39  
            }  // Line 40
        }       
        CPoint[] res = new CPoint[k];
        // Then make a second pass to get k closest points into result. 
        while (!pq.isEmpty()) {     // Line 44
            res[--k] = pq.poll();   // Line 45                   
        }                           // Line 46

        return res;
    }

    private static double distance(CPoint a, CPoint b) {        
        return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
    }

}
Run Code Online (Sandbox Code Playgroud)

题:

  1. 第35行,第39行分别和单独的时间复杂度是多少?

  2. 35-40行(整体)的时间复杂度是多少?

  3. 44-46行(整体)的时间复杂度是多少?

  4. 在最佳,最差和平均情况下,整个方法getKNearestPoints()的总体时间复杂度是多少?如果n >> k怎么办?如果我们没有n >> k怎么办?

实际上,这些问题在我的技术面试中只是几个问题,但我对此仍然感到困惑。任何帮助表示赞赏。

har*_*nds 5

从外观上看,我认为编写此代码的人必须知道这些问题的答案。

无论如何,此处的Priority Queue基于Max Heap实现。

因此,复杂性如下:

第35行 - O(log k)在堆中插入元素的时间。插入时在堆中遵循自下而上的方法。

第37行 - O(1)检查堆大小的时间,通常与堆一起维护。

第39行 - O(log k)删除堆头的时间,将应用堆根处的heapify方法来删除堆的顶部。

35-40行:从以上复杂性可以看出,一次迭代的总体复杂度将为O(log k)。该循环针对n元素运行,因此总体复杂度为O(n log k)

44-46行:再次检查堆的大小的复杂性O(1),轮询为O(log k)。因此,我们正在执行轮询k时间。循环的整体复杂度为O(k log k)

总体复杂性将保持不变O(n log k)

是学习该主题的好地方。

  • 好的,从数学上讲,O(logk)+ O(logk)= O(2logk)= O(logk ^ 2)= O(logk),我的意思是可以用所有这些方式编写它们。 (2认同)
  • 完全有道理!谢谢!还有一个问题,为什么我们可以“放弃”“第二遍以使k个最接近的点进入结果”的时间。(klogk)?总体为O(nlogK),但不是O(nlogk)+ O(klogk) (2认同)