Skip to content

随机选择算法


题目链接

https://leetcode.cn/problems/kth-largest-element-in-an-array/

无序数组中寻找第 K 大的数

给定整数数组 nums  和整数  k,请返回数组中第  k  个最大的元素

请注意,你需要找的是数组排序后的第 k  个最大的元素,而不是第 k  个不同的元素

你必须设计并实现时间复杂度为 O(n)  的算法解决此问题

思路分析

沿用了随机快排的思路,随机一个数,划分区间,判断传进来的 i 在哪个区间,然后递归调用

区别于随机快排,随机选择排序对不符合要求的区间无需排序

代码实现

java
class Solution {
    // 表示边界
    public static int first;
    public static int last;

    public int findKthLargest(int[] nums, int k) {
        return randomizeSelect(nums, nums.length - k);
    }

    // 返回的是数组排好序后,i 位置的值
    public int randomizeSelect(int[] arr, int i) {
        int ans = 0;
        for (int l = 0, r = arr.length - 1; l <= r;) {
            int x = arr[l + (int) (Math.random() * (r - l + 1))];
            partition(arr, l, x, r);
            if (i < first){
                r = first - 1;
            } else if (i > last) {
                l = last + 1;
            } else {
                ans = arr[i];
                break;
            }
        }
        return ans;
    }

    public void partition(int[] arr, int l, int x, int r) {
        first = l;
        last = r;
        int i = l;
        while (i <= last) {
            if (arr[i] == x) {
                i++;
            } else if (arr[i] < x) {
                swap(arr, i, first);
                first++;
                i++;
            } else {
                swap(arr, i, last);
                last--;
            }
        }
    }

    public void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

复杂度分析

(1)时间复杂度 O(n)

(2)额外空间复杂度 O(1)

除了用原数组,都是有限级的变量,递归都没用,判断范围,去哪个区间找