Leetcode NO.215 Kth Largest Element In An Array 数组中的第K个最大元素

1.问题描述

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

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

2.测试用例

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

3.提示

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

4.代码

1.基于堆排序
code
/**
     * 基于堆排序
     *
     * @param nums nums
     * @param k    k
     * @return res
 */
public int findKthLargestWithBigHeapSort(int[] nums, int k) {
    int n = nums.length;
    int heapSize = n;
    //构建大顶堆
    buildBigHeapify(nums, heapSize);
    //删除第 n - k个元素
    for (int i = n - 1; i > n - k; i--) {
        exchangeArrayEle(nums, 0, i);
        heapSize--;
        maxHeapfiy(nums, 0, heapSize);
    }
    //返回堆顶即可
    return nums[0];
}


/**
     * 构建大顶堆
     * @param nums 数组
     * @param heapSize 堆大小
*/
private void buildBigHeapify(int[] nums, int heapSize) {
    for (int i = heapSize / 2 - 1; i >= 0; i--) {
        //递归构建
        maxHeapfiy(nums, i, heapSize);
    }
}

/**
     * 构建大顶堆
     * @param nums 数组
     * @param top 堆元素
     * @param heapSize 堆大小
*/
private void maxHeapfiy(int[] nums, int top, int heapSize) {
    int left = top * 2 + 1;
    int right = top * 2 + 2;
    int largest = top;

    if (right < heapSize && nums[right] > nums[largest]) {
        largest = right;
    }
    if (left < heapSize && nums[left] > nums[largest]) {
        largest = left;
    }
    if (top != largest) {
        exchangeArrayEle(nums, top, largest);
        maxHeapfiy(nums, largest, heapSize);
    }
}


/**
     * 交换数组元素
     * 临时变量法
     *
     * @param nums 数组
     * @param i 待交换元素i
     * @param j 待交换元素j
 */
public static void exchangeArrayEle(int[] nums, int i, int j) {
    Assert.assertNotNull(nums);
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}
复杂度
* 时间 O(nlogn)
* 空间 O(logn)
2.基于快速选择排序
code
/**
     * 基于快速选择排序
     * 时间 O(n) 证明过程可以参考《算法导论》9.2
     * 空间 O(nlongn)
     *
     * @param nums nums
     * @param k    k
     * @return res
 */
public int findKthLargestWithQuickSelectSort(int[] nums, int k) {
    return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}

/**
     * 快速选择(单路)排序
     * @param nums 数组
     * @param start 起始元素位置
     * @param end 结束元素位置
     * @param k 查找位置
     * @return
 */
private int quickSelect(int[] nums, int start, int end, int k) {
    int partiton = randomPartiton(nums, start, end);
    if (partiton == k) {
        return nums[k];
    } else {
        return k < partiton ? quickSelect(nums, start, partiton - 1, k) : quickSelect(nums, partiton + 1, end, k);
    }
}

/**
     * 随机分区
     * @param nums 数组
     * @param start 起始元素位置
     * @param end 结束元素位置
     * @return
*/
private int randomPartiton(int[] nums, int start, int end) {
    int random = start + new Random().nextInt(end - start + 1);
    SortUtils.exchangeArrayEle(nums, start, random);
    return partition(nums, start, end);
}

/**
     * 双指针快排
     * @param nums 数组
     * @param start 起始元素位置
     * @param end 结束元素位置
     * @return
 */
private int partition(int[] nums, int start, int end) {
    int left = start, right = end;
    int povit = nums[start];
    while (left < right) {
        while (left < right && nums[right] >= povit) {
            right--;
        }
        while (left < right && nums[left] <= povit) {
            left++;
        }
        SortUtils.exchangeArrayEle(nums, left, right);
    }
    SortUtils.exchangeArrayEle(nums, left, start);
    return left;
}
复杂度
* 时间 O(n) 
* 空间 O(longn)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值