Leetocde 215. Kth Largest Element in an Array

本文深入解析了两种高效算法:快速选择和最小堆,用于解决寻找数组中第K大的元素问题。通过详细阐述算法原理,提供代码实现,帮助读者理解并掌握这些算法的实际应用。

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

这是一道让我收获很大的题,解题思路是使用quick select排序。首先选出一个pivot(为了方便,把数组的最后一个元素nums[high] 设置成pivot), 然后扫描整个数组。使用了两个指针: i and j,[low, i) 是小于pivot的元素,[i, j) 是大于pivot的元素,[j, high)是未知探索区域。当扫描完整个数组后,将 nums[i] 和 nums[high] 交换位置,这样 index为 i 的元素即 pivot 在整个数组的位置已经固定下来(左边的元素比他小,右边的元素比他大),我们数一下pivot从大到小排在第几位记为 count。如果count = k, 则代表我们找到了想要的元素; count > k说明 pivot 的值小了,我们需要在它的右边继续找 kth largest element; 如果count < k, 意味着pivot的值大了,我们需要在他的左手边找到 (k - count)th largest element, 那么这个元素就是整个数组里 kth largest element。代码如下:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return quickSelect(nums, 0, nums.length - 1, k);
    }
    private int quickSelect(int[] nums, int low, int high, int k){
        int i = low;
        // Here we pick nums[high] as the pivot
        for(int j = low; j < high; j++){
            if(nums[j] <= nums[high]){
                swap(nums, i++, j);
            }
        }
        swap(nums, i, high);
        int count = high - i + 1;
        if(count == k){
            return nums[i];
        }else if(count > k){
            return quickSelect(nums, i + 1, high, k);
        }else{
            return quickSelect(nums, 0, i - 1, k - count);
        }
    }
    private void swap(int[] arr, int left, int right){
        int temp = arr[right];
        arr[right] = arr[left];
        arr[left] = temp;
    }
}

最近学习了heap以后,又掌握了另一种方法:创建一个大小为k的min heap, 其物理意义就是我们当前找到的最大的k个数。先把数组的前k个数放进去,然后继续遍历后面的数,每次都和堆顶的数进行比较,如果比堆顶的数要大,就把堆顶的数pop()出去,再offer()当前的数。当这一个过程完成以后,堆顶的数就是我们要的 kth largest element。还有一个总结就是,关于比较器的lambda表达式,你需要脑补一个<0在后面。例如(a,b) -> a - b,可以理解成当 a - b < 0即 a < b 时,a排在b的前面。因此这是一个最小堆。代码如下:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, (a,b) -> a - b);
        for(int i = 0; i < k; i++){
            minHeap.offer(nums[i]);
        }
        for(int i = k; i < nums.length; i++){
            int temp = minHeap.peek();
            if(nums[i] > temp){
                minHeap.poll();
                minHeap.offer(nums[i]);
            }
        }
        return minHeap.peek();
    }
}

https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/partitionfen-er-zhi-zhi-you-xian-dui-lie-java-dai-/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值