66、数组中的第K个最大元素(反复阅读其中的partition函数,很重要!!!)

本文介绍了一种在未排序数组中查找第k个最大元素的方法。通过两种方式实现:一是直接利用排序函数;二是采用快速排序的思想进行优化,提高查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
在未排序的数组中找到第 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
说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
代码:直接调用库函数进行

class Solution {
    public int findKthLargest(int[] nums, int k) {
       int []copy =  Arrays.copyOf(nums, nums.length);
       Arrays.sort(copy);

       return copy[nums.length - k];
    }
}

但是没有什么技术含量

自己尝试使用快排的partition函数改造进行书写
但是跑起来感觉好慢

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int res = findKthLargest(nums,0,nums.length - 1,k);
        return res;
    }
    public static int findKthLargest(int[] nums,int l ,int r, int k) {
        int p = partition(nums,l,r,k);
        if(p - l + 1 == k){
            return nums[p];
        }
        if(p - l + 1 > k){
            return findKthLargest(nums,l,p - 1,k);
        }else{
            return findKthLargest(nums,p + 1,r, k - (p - l + 1));
        }
    }

//    按照递减的顺序进行排序
    public static int partition(int nums[], int l, int r,int k) {
        int i = l;
        int tem = nums[r];
        while (l < r) {
            if (nums[l] > tem) {
                int tems = nums[l];
                nums[l] = nums[i];
                nums[i] = tems;
                i++;
            }
            l ++;
        }
        int tems = nums[i];
        nums[i] = nums[l];
        nums[l] = tems;

        return i;
    }
}

排名靠前的代码

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int left=0,right=nums.length-1;
        while(left<right){
            int pivot = partition(nums, left,right);
            if(pivot ==k-1) {
                return nums[pivot];
            } else if(pivot>k-1){
                right=pivot-1;
            } else {
                left=pivot+1;
            }
        }
        return nums[left];
    }
    private int partition(int[] nums,int left,int right) {
        //先获取三个数的中位数
        int pivot = median3(nums,left,right);
        //int pivot = nums[left];

        int start=left,end=right-1;
        while(start<end) {
            //从pivot左边找起,停在第一个比pivot小的地方,等待交换
            while(nums[++start]>pivot) {}
            //从pivot右边朝气,停在第一个比pivot大的地方,等待交换
            while(nums[--end]<pivot) {}
            if(start<end) {
                swap(nums,start,end);
            }
        } 
        //此时,交换start与pivot
        swap(nums,start, right-1);
        return start;
    }
    
    private int median3(int[] nums,int left, int right){
        int median=(left+right)/2;
        if(nums[left]<nums[median]) {
            swap(nums, left, median);
        }
        if(nums[left]<nums[right]) {
            swap(nums,left, right);
        }
        if(nums[median]<nums[right]) {
            swap(nums, median, right);
        }
        swap(nums, median, right-1);
        return nums[right-1];
        
    }
    
    private void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值