LeetCode 215. Kth Largest Element in an Array

题目描述

  • Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
    For example,
    Given [3,2,1,5,6,4] and k = 2, return 5.
  • 地址

问题分析

  • 这是十分经典的 Top K 问题。和剑指offer-最小的K个数类似
  • 方法一:
    用一个大小为K的最小堆,先将数组中前K个元素入堆,然后继续遍历数组中其他元素,若当前元素大于堆顶元素,便将堆顶弹出,将当前元素入堆。这样,最终,堆里便是该数组中最大的K个数,堆顶元素便是第 K大的数。
    时间复杂度:O(NlogK)
    同理,如果找第K小的数字,便维护一个大小为K的大根堆,若当前元素小与对顶元素,便将堆顶弹出,将当前元素入堆。这样,最终,堆里便是该数组中最小的K个数,堆顶元素便是第 K小的数。
  • 方法2:Quick Select
    类似于快排。就是不断优化pivot所在的位置,最终使pivot位于 nums.length - k 处。这样nums[nums.length - k] 便是 第K大的数字。
    复杂度分析:平均为O(N),最差情况下为 O(N^2)
    这里写图片描述

经验教训

  • 解决 Top k 问题的两大思路
  • Quick Select 复杂度分析

代码实现

  • 最小堆
    public int findKthLargest(int[] nums, int k) {
        if (nums == null || k <= 0 || k > nums.length) {
            return -1;
        }
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        int i = 0;
        while (i < k) {
            minHeap.add(nums[i++]);
        }
        while (i < nums.length) {
            if (nums[i] > minHeap.peek()) {
                minHeap.poll();
                minHeap.add(nums[i]);
            }
            i++;
        }
        return minHeap.peek();
    }
  • Quick Select
    public int findKthLargest(int[] nums, int k) {
        if (nums == null || k <= 0 || k > nums.length) {
            return -1;
        }
        int begin = 0;
        int end = nums.length - 1;
        while (begin <= end) {
            int pivotIndex = partition(nums, begin, end);
            if (pivotIndex > nums.length - k) {
                end = pivotIndex - 1;
            }else if (pivotIndex < nums.length - k) {
                begin = pivotIndex + 1;
            }else {
                return nums[pivotIndex];
            }
        }
        return -1;
    }

    public int partition(int[] nums, int begin, int end) {
        int pivot = nums[begin];
        while (begin < end) {
            while (begin < end && nums[end] >= pivot) {
                end--;
            }
            nums[begin] = nums[end];
            while (begin < end && nums[begin] <= pivot) {
                begin++;
            }
            nums[end] = nums[begin];
        }
        nums[begin] = pivot;
        return begin;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值