题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
法一 适合处理海量数据容器法
思路(书):
创建一个大小为k的容器,来存储最小的k个数。
遍历数组,对于每一个数字,当容器未满时,直接丢进容器。当容器已满时,而当前数字又小于容器中的最大数字,我们需要将其替换出来。
这个容器可以用最大堆(书上用了红黑树,容我后面学学再说),堆顶永远是这个容器中的最大数字。每当我们遍历到一个数字,只需和堆顶比较即可。
java中可以用优先队列来实现最大堆,这样在我们往堆中插入一个元素时,会进行比较自动将当前容器中的最大值放在堆顶。
最大堆定义:
- 它是一颗完全二叉树,它可以是空
- 树中结点的值总是不小于其孩子结点的值
- 每一个结点的子树也是一个堆
用优先队列实现大顶堆
PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器comparator来排序其元素。队列默认自然顺序排列,所以在这里使用大堆顶的话,要重写comparator。
代码是看了这个老哥的->牛客网id:披萨大叔,不然我的脑袋瓜是想不到优先队列的。
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<>();
if(input.length < k || k == 0)
return res;
if(input.length == k){
for(int in : input)
res.add(in);
return res;
}
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
//数组的前k个元素无条件入堆
//for(int i=0; i<k; i++){
// maxHeap.offer(input[i]);
//}
for(int i=0; i<input.length; i++){
if(maxHeap.size() < k){
maxHeap.offer(input[i]);
}
//如果当前元素大于堆顶(堆最大值)值,跳过
//如果小于的话,将堆顶出堆,当前元素入堆
else if(input[i] < maxHeap.peek() ){
maxHeap.poll();
maxHeap.offer(input[i]);
}
}
//遍历优先队列
//for(Integer resx : maxHeap)
// res.add(resx);
while (!maxHeap.isEmpty())
res.add(maxHeap.poll());
return res;
}
}