我在Leetcode遇到了第k个最大的问题
输入:[3,2,1,5,6,4]和k=2,输出:5
建议的解决方案:

 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;
}

分区不取o(n),主函数中的while循环不取o(logn),所以应该是o(nlogn)?这看起来像是使用了快速排序,但是快速排序的运行时是O(nlogn)如果quicksort取O(n),这是有意义的,但不是请帮助我了解发生了什么事?

最佳答案

这是一个随机算法,具有平均/预期的o(n)运行时。这是因为在随机洗牌输入列表之后,我们通常有足够好的支点,在每次分区函数调用之后,如果找不到目标,我们会将列表(下一步搜索)大约减少一半这意味着即使我们运气不好,不得不不断地调用分区函数,我们也会不断地将列表的大小减少一半,因此平均运行时间仍然只有o(n),因为o(n)+o(n/2)+o(n/4)+…+O(1)仍然是O(n)。

关于algorithm - 第K个最大数字,为什么此运行时为O(n)而不是O(nlogn),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50939049/

10-11 19:35