简体   繁体   English

第K个最大数字,为什么此运行时为O(n)而不是O(nlogn)

[英]Kth largest number, why the runtime of this is O(n) not O(nlogn)

I came across kth largest number problem in Leetcode 我在Leetcode中遇到了第k个最大数字问题

Input: [3,2,1,5,6,4] and k = 2, Output: 5 输入:[3,2,1,5,6,4],k = 2,输出:5

Suggested Solution: 建议的解决方案:

 public int findKthLargest(int[] nums, int k) {
    shuffle(nums);
    k = nums.length - k;
    int lo = 0;
    int hi = nums.length - 1;
    while (lo < hi) {
        final int j = partition(nums, lo, hi);
        if(j < k) {
            lo = j + 1;
        } else if (j > k) {
            hi = j - 1;
        } else {
            break;
        }
    }
    return nums[k];
}

private int partition(int[] a, int lo, int hi) {

    int i = lo;
    int j = hi + 1;
    while(true) {
        while(i < hi && less(a[++i], a[lo]));
        while(j > lo && less(a[lo], a[--j]));
        if(i >= j) {
            break;
        }
        exch(a, i, j);
    }
    exch(a, lo, j);
    return j;
}

private void exch(int[] a, int i, int j) {
    final int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

private boolean less(int v, int w) {
    return v < w;
}

Doesn't partition take O(n) and the while loop in the main function take O(log n) so it should be O(nlog n)? 分区不占用O(n)吗,而main函数中的while循环占用O(log n),所以应该是O(nlog n)? This looks like it uses Quicksort but the runtime for quicksort is O(nlogn). 看起来它使用了Quicksort,但是quicksort的运行时是O(nlogn)。 If quicksort takes O(n), this makes sense but it does not. 如果quicksort取O(n),这是有道理的,但没有意义。 Please help me understand what is going on? 请帮助我了解发生了什么事?

This is a randomized algorithm that has average/expected O(n) runtime. 这是具有平均/预期O(n)运行时间的随机算法。 This is because after randomly shuffling the input list, we typically have pivots good enough to expect that after each partition function call if we don't find the target yet we reduce our list (to be search next) roughly by half. 这是因为在随机调整输入列表后,我们通常具有足够好的枢轴,可以期望在每次分区函数调用之后,如果我们找不到目标,但我们会将列表(将在下一个搜索中)大致减少一半。 This means even though if we not lucky and have to continuously call partition function we continuously keep reducing our list's size by half, therefore the average runtime is still only O(n) since O(n) + O(n/2) + O(n/4) + ... + O(1) is still O(n). 这意味着,即使我们不走运并且不得不连续调用分区函数,我们也会不断将列表大小减小一半,因此,由于O(n)+ O(n / 2)+ O,平均运行时间仍然仅为O(n) (n / 4)+ ... + O(1)仍然是O(n)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM