题目
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
分析
思路一:
使用堆(heap)来实现,Java中堆默认是从小到大排序的,为此 需要重写比较函数。其中comareTo函数代码测试如下:
public static void main(String[] args) {
Integer s1 = 2;
Integer s2 = 5;
Integer s3 = 5;
System.out.println("<:"+s1.compareTo(s2));
System.out.println(">:"+s2.compareTo(s1));
System.out.println("=:"+s2.compareTo(s3));
}
输出如下:
重新构造比较器如下:
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k,
new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
其中 o2.compareTo(o1)代表从大到小排序,即为最大堆的实现,反之则为从小到大,最小堆。
最大堆:
siftDown(int k, E x)方法,该方法的作用是从k指定的位置开始,将x逐层向下与当前点的左右孩子中较小的那个交换,直到x小于或等于左右孩子中的任何一个为止。
思路见代码,有注释。
时间复杂度:O(N)
空间复杂度:O(N)
代码:
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Comparator;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> result = new ArrayList<Integer>();
int length = input.length;
//边界条件
if(input==null||k<=0||k>length) return result;
//使用优先级队列构造最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k,
new Comparator<Integer>(){
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
//向最大堆中添加input中最小的k个数
for(int i=0;i<length;i++){
if(maxHeap.size()!=k){
maxHeap.offer(input[i]);
} else if(maxHeap.peek()>input[i]){
Integer tmp = maxHeap.poll();
tmp = null;
maxHeap.offer(input[i]);
}
}
//从最大堆添加到Arraylist中
for(Integer integer:maxHeap){
result.add(integer);
}
return result;
}
}