leetcode215.数组中的第k个大的数

依旧使用快排中的 Partion解决问题(分治)

需要注意的是,本题如果不对Partion进行随机优化,那么有些样例通过时间复杂度较高,所以在Partion中加入了随机优化。

class Solution{

    public int findKthLargest(int[] nums, int k) {
        if (k == 0 || nums.length == 0)
            return -1;
        return quickSearch(nums, 0, nums.length - 1, k);
    }

    private int quickSearch(int[] nums, int l, int r, int k) {
        // 每快排切分1次,找到排序后下标为j的元素,如果j+1恰好等于k,nums[j]即为所求
        int j = randPartition(nums, l, r);
        if (j + 1 == k){
            return nums[j];
        }
        if (j + 1 < k){
            return quickSearch(nums, j + 1, r, k);
        }
        if (j + 1 > k){
            return quickSearch(nums, l, j - 1, k);
        }
        return -1;
    }

    // 快排切分,返回下标j,使得比nums[j]大的数都在j的左边,比nums[j]小的数都在j的右边
    private static int randPartition(int[] nums, int l, int r) {
        int index = (int)(Math.random()*(r-l+1))+l;
        swap( nums, l, index);
        int v = nums[l];
        int j = l;
        for (int i = l + 1; i <= r; i++) {
            if (nums[i] > v){
                swap(nums, j+1, i);
                j ++;
            }
        }
        swap(nums, l, j);
        return j;
    }

    // 自定义swap函数
    private static void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public static void main(String[] args) {
        int[] temp = {4, 1, 5, 3, 2};
        int res = new Solution().findKthLargest(temp, 3);
        System.out.println(res);
    }
}

但是最初选取 left 和 right 两个边界中的随机数时,是采用下面的代码中的两种方式,结果是无法AC的,在idea中有时候也会报错,尚未发现这种随机数生成的问题在哪!!!

import java.util.Random;

class Solution{

    private static Random random = new Random();

    public int findKthLargest(int[] nums, int k) {
        if (k == 0 || nums.length == 0)
            return -1;
        return quickSearch(nums, 0, nums.length - 1, k);
    }

    private int quickSearch(int[] nums, int l, int r, int k) {
        // 每快排切分1次,找到排序后下标为j的元素,如果j+1恰好等于k,nums[j]即为所求
        int j = partition(nums, l, r);
        if (j + 1 == k){
            return nums[j];
        }
        if (j + 1 < k){
            return quickSearch(nums, j + 1, r, k);
        }
        if (j + 1 > k){
            return quickSearch(nums, l, j - 1, k);
        }
        return -1;
    }

    // 快排切分,返回下标j,使得比nums[j]大的数都在j的左边,比nums[j]小的数都在j的右边
    private static int partition(int[] nums, int l, int r) {
        //int index = l + random.nextInt(r - l) + 1;
        int index = l + random.nextInt(r) % (r-l+1) + l;//生成随机索引
        swap( nums, l, index);
        int v = nums[l];
        int j = l;
        for (int i = l + 1; i <= r; i++) {
            if (nums[i] > v){
                swap(nums, j+1, i);
                j ++;
            }
        }
        swap(nums, l, j);
        return j;
    }

    // 自定义swap函数
    private static void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public static void main(String[] args) {
        int[] temp = {4, 1, 5, 3, 2};
        int res = new Solution().findKthLargest(temp, 3);
        System.out.println(res);
    }
}

你可能感兴趣的:(LeetCode)