剑指offer_076 数组中的第k大的数字

题目:

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

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

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

提示:

1 <= k <= nums.length <= 104
-104 <= nums[i] <= 104

代码一:普通快排

class Solution {
    public int findKthLargest(int[] nums, int k) {
        quickSort(nums, 0, nums.length - 1);
        return nums[nums.length - k];
    }
     public void quickSort(int[] nums, int left, int right) {
        if (left >= right) {
            return;
        }
        // 选取标记点,并使得标记点左侧的式子比标记数字大,右侧的数字比标记数字小
        int pivot = getPivot(nums, left, right);
        quickSort(nums, left, pivot - 1);
        quickSort(nums, pivot + 1, right);
    }

    public int getPivot(int[] nums, int left, int right) {
        // 从 [left,right] 中随机取一个数字,可以有效避免当数组基本有序时,快排失效
        Random randoms = new Random();
        int random = randoms.nextInt(right - left + 1) + left;
        // 交换 random 和 right 位置的元素,取标记点数字为 nums[right]
        swap(nums, random, right);
        int index = left;
        // 找到 [left, right - 1] 中所有比 nums[right] 小的数字,并依次放置在数列左侧
        for (int i = left; i < right; i++) {
            if (nums[i] < nums[right]) {
                swap(nums, i, index++);
            }
        }
        // 循环结束后, [left, index - 1] 的数字均比 nums[right] 小,
        // 且 [count, right -1] 的数字均比 nums[right] 大
        // 交换 nums[index] 和 nums[right] 即可达到目的
        swap(nums, index, right);
        // index 为标记数字的当前位置
        return index;
    }

    public void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

}

代码二:只找基准的快排

class Solution {
    private static final Random RANDOM = new Random();

    public int findKthLargest(int[] nums, int k) {
        int target = nums.length - k;
        int start = 0, end = nums.length - 1;
        int pivot = getPivot(nums, start, end);
        while (pivot != target) {
            if (pivot > target) {
                end = pivot - 1;
            } else {
                start = pivot + 1;
            }
            pivot = getPivot(nums, start, end);
        }
        return nums[pivot];
    }

    private int getPivot(int[] nums, int start, int end) {
        // 从 [start,end] 中随机取一个数字,可以有效避免当数组基本有序时,快排失效
        int random = RANDOM.nextInt(end - start + 1) + start;
        swap(nums, random, end);
        int index = start - 1;
        for (int i = start; i < end; i++) {
            if (nums[i] < nums[end]) {
                swap(nums, i, ++index);
            }
        }
        swap(nums, ++index, end);
        return index;
    }

    private void swap(int[] nums, int index1, int index2) {
        // 此处可以增加判断 index1 和 index2 是否相等,若相等,不需要进行交换
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

注意:

好好学习。

参考链接:

力扣

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值