【快排】215. 数组中的第K个最大元素

题目:

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

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

题解:

快排每轮partition就可以将选中的pivot放到其最终有序位置,当某轮pivot被放到第k大元素位置(从小到大有序序列的下标n-k处)时,确定该pivot为结果

pivot的选择利用随机数可以防止最差时间复杂度。

nextInt()用法:

会随机生成一个整数,这个整数的范围就是int类型的范围-2^31 ~ 2^31-1,但是如果在nextInt()括号中加入一个整数a那么,这个随机生成的随机数范围就变成[0,a)。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        //第k大元素,即排序后下标为n-k的元素,使用partition方法确定下标n-k元素
        int target = nums.length - k;
        int from = 0, to = nums.length - 1;
        while (true) {
            int idx = partition(nums, from, to); //每次partition返回pivot插入的位置
            if (idx == target) { //如果插入的位置是目标位置,找到第k大元素
                return nums[target];
            } else if (idx > target) { //如果插入的位置大于目标位置,目标位置搜索范围应该在idx左边
                to = idx - 1;
            } else { //如果插入的位置小于目标位置,目标位置搜索范围应该在idx右边
                from = idx + 1;
            }
        }
    }

    Random rand = new Random();
    //返回单次partition确定pivot元素固定到的位置
    private int partition(int[] nums, int from, int to) {
        int pivotIndex = rand.nextInt(to - from + 1) + from;
        int pivot = nums[pivotIndex];
        //随机pivot交换到头部
        int temp = nums[from];
        nums[from] = pivot;
        nums[pivotIndex] = temp;

        int left = from, right = to;
        while (left < right) {
            while (left < right && nums[right] >= pivot) { //从右往左找到第一个<pivot的
                right--;
            }
            if (left < right) {
                nums[left] = nums[right];                
            }
            while (left < right && nums[left] <= pivot) { //从左往右找到第一个>pivot的
                left++;
            }
            if (left < right) {
                nums[right] = nums[left];                
            }
        }
        nums[left] = pivot; //最后把pivot放到left的位置
        return left;
    }
}

参考:力扣 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值