我正在尝试解决广受欢迎的面试问题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))。答案 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 足够大,那么就值得了。)