2021-08-23(215. 数组中的第K个最大元素)

该博客讲解了如何使用大根堆数据结构实现查找数组中第k大的元素。首先建立大根堆,然后通过删除k-1个根节点并调整堆结构,最终返回堆顶作为答案。关键方法包括`findKthLargest`、`buildMaxHeap`和`maxHeapify`。
摘要由CSDN通过智能技术生成
class Solution {
    public int findKthLargest(int[] nums, int k) {
        int heapSize =nums.length;
        buildMaxHeap(nums,heapSize);
        for(int i=heapSize-1;i>heapSize-k;--i){
            swap(nums,0,i);
            //这里的i应该理解为当前节点下标碰巧为其前面所有节点的个数
            maxHeapify(nums,i,0);
        }
        return nums[0];
    }
    public void buildMaxHeap(int[]a,int heapSize){
        for(int i=heapSize/2-1;i>=0;--i){
            maxHeapify(a,heapSize,i);
        }
    }
    //调整位置为i的节点
    public void maxHeapify(int[] a,int heapSize,int i){
        int leftSon=i*2+1;
        int rightSon=i*2+2;
        int largest=i;
        if(leftSon<heapSize&&a[leftSon]>a[largest]){
            largest=leftSon;
        }
        if(rightSon<heapSize&&a[rightSon]>a[largest]){
            largest=rightSon;
        }
        if(largest!=i){
            swap(a,largest,i);
            maxHeapify(a,heapSize,largest);
        }
    }
    public void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}

大根堆方法:建立一个大根堆,删除 k - 1次根节点(即把根与正确位置元素交换,再调整交换到根节点的节点)后堆顶元素就是我们要找的答案。

可以使用快速选择算法来解决该问题,其中快速选择算法是基于快速排序的,它可以在O(n)的时间复杂度内找到第k个最大元素。 具体实现步骤如下: 1. 定义一个函数 `quickSelect(nums: IntArray, k: Int, left: Int, right: Int): Int`,其中 `nums` 是给定的整数数组,`k` 是要查找的第k个最大元素,`left` 和 `right` 分别是数组的左右边界。 2. 在 `quickSelect` 函数中,使用快速排序的思想,选择一个基准元素 `pivot`,并将数组中小于等于 `pivot` 的元素移到左边,大于 `pivot` 的元素移到右边。 3. 判断 `k` 和 `pivot` 在数组中的位置关系,如果 `k` 小于等于 `pivot` 的下标,说明第k个最大元素数组的左半部分,递归调用 `quickSelect(nums, k, left, pivot - 1)`。 4. 如果 `k` 大于 `pivot` 的下标,说明第k个最大元素数组的右半部分,递归调用 `quickSelect(nums, k, pivot + 1, right)`。 5. 如果 `k` 等于 `pivot` 的下标,说明第k个最大元素就是 `pivot`,直接返回 `pivot`。 6. 循环以上步骤,直到找到第k个最大元素。 完整的代码如下: ```kotlin fun findKthLargest(nums: IntArray, k: Int): Int { return quickSelect(nums, k, 0, nums.size - 1) } fun quickSelect(nums: IntArray, k: Int, left: Int, right: Int): Int { val pivot = partition(nums, left, right) return when { k < nums.size - pivot -> quickSelect(nums, k, pivot + 1, right) k > nums.size - pivot -> quickSelect(nums, k - (nums.size - pivot), left, pivot - 1) else -> nums[pivot] } } fun partition(nums: IntArray, left: Int, right: Int): Int { var i = left var j = right val pivot = nums[left] while (i < j) { while (i < j && nums[j] <= pivot) j-- nums[i] = nums[j] while (i < j && nums[i] >= pivot) i++ nums[j] = nums[i] } nums[i] = pivot return i } ``` 其中 `partition` 函数是快速排序中的分区函数,用于将数组中小于等于基准元素元素移到左边,大于基准元素元素移到右边,最终返回基准元素的下标。在 `quickSelect` 函数中,我们根据 `k` 和 `pivot` 的位置关系,判断第k个最大元素数组的左半部分、右半部分还是就是 `pivot`,并递归调用 `quickSelect` 函数,直到找到第k个最大元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值