LeetCode:数组中的第K个最大元素【215】 LeetCode:数组中的第K个最大元素【215】

题目描述

在未排序的数组中找到第 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 ≤ 数组的长度。

题目分析

  我们主要来学习一个新的集合类型——优先队列。优先队列作用是保证每次取出的元素都是队列中权值最小的

  这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序,也可以通过构造时传入的比较器。我们这里是数组,比较数字大小即可,不需要比较器。

  Java中PriorityQueue实现了Queue接口,不允许放入null元素;其通过堆实现,具体说是通过完全二叉树实现的小顶堆(任意一个非叶子节点的权值,都不大于其左右子节点的权值)。线程不安全。

  既然是小顶堆那么就是下图这样:

  LeetCode:数组中的第K个最大元素【215】
LeetCode:数组中的第K个最大元素【215】

  无论堆中有几个元素,堆顶的元素一定是最小的,所以我们让堆中仅保留K个元素,那么处于堆顶的元素一定是第K大的(或者说是最小的)。我们始终维持堆的元素在K个,每当超过后,我们就POLL出去堆顶元素,那么最后剩下的K个元素,就是整个数组中最大的K个元素。

  LeetCode:数组中的第K个最大元素【215】
LeetCode:数组中的第K个最大元素【215】

  比如我们取第三大元素,那么我们的堆大小就恒定为3,每次 将入新元素,重新构造堆,最后的堆顶元素3,就是第3大元素。

关于PriorityQueue的进一步学习,可以参考这篇文章:

    https://github.com/CarpenterLee/JCFInternals/blob/master/markdown/8-PriorityQueue.md  

Java题解

class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer>  queue = new PriorityQueue<>();
        for(int num:nums) {
            queue.offer(num);
            if(queue.size()>k)
                queue.poll();
        }
        return queue.peek();
    }
}