题目:
设计一个算法,找出数组中最小的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问题在下一个博客中会提讲解!