leetcode:最小k个数 (十一)

2,104 阅读1分钟

题目:

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]

class Solution {    public int[] smallestK(int[] arr, int k) {    }}

题解:

用堆的方法解决问题:

我们用一个大根堆实时维护数组的前 k小值。首先将前 k个数插入大根堆中,随后从第 k+1个数开始遍历,如果当前遍历到的数比大根堆的堆顶的数要小,就把堆顶的数弹出,再插入当前遍历到的数。最后将大根堆里的数存入数组返回即可。(由于 C++ 语言中的堆(即优先队列)为大根堆,我们可以这么做。而 Python 语言中的对为小根堆,因此我们要对数组中所有的数取其相反数,才能使用小根堆维护前 k小值。  而java中的堆即使默认为小根堆,也可以被人工替换成大根堆。

class Solution {
    public int[] smallestK(int[] arr, int k) {
        int[] vec = new int[k];
        if (k == 0) { // 排除 0 的情况
            return vec;
        }
        PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
            public int compare(Integer num1, Integer num2) {
                return num2 - num1;
            }
        });
        for (int i = 0; i < k; ++i) {
            queue.offer(arr[i]);
        }
        for (int i = k; i < arr.length; ++i) {
            if (queue.peek() > arr[i]) {
                queue.poll();//获取但不删除队首元素
                queue.offer(arr[i]);//插入元素并返回false当插入失败
            }
        }
        for (int i = 0; i < k; ++i) {
            vec[i] = queue.poll();获取并删除队首元素,再调整
        }
        return vec;
    }
}

思路:

用大根堆的数据结构,前k个已经是大根堆,只需要用最大的也就是第k大的数每次和后面比较,最后得出的前k个数就是最小的k个数

关于java中的优先队列priorityqueue问题在下一个博客中会提讲解!