两种解法:
一种基于Partition(将要改变输入数组),时间复杂度O(n)
另一种使用最大堆的方法(可以解决海量数据),时间复杂度O(nlogk)
重点:最大堆的建立方法(从下往上O(logn))
//Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆
//建最大堆
import java.util.Arrays;
/**
* 问题描述:输入n个整数,输出其最小的k个数
* 输入:4,5,1,6,2,7,3,8
* 输出:1,2,3,4
* Created by lxq on 2017/9/3.
*/
public class Problem2 {
public static void main(String[] args){
Problem2 test = new Problem2();
int[] array = {4,5,1,6,2,7,3,8};
test.getLeastNumbers(array,2);
}
public void getLeastNumbers(int[] array,int k ){
if(array==null||k<0||k>array.length)
return;
int[] kArray = Arrays.copyOfRange(array,0,k);
buildMaxHeap(kArray);
//整个数组的 最大元素 总是在最大堆的第一个,即kArray[0]
for(int i=k;i<array.length;i++){
if(array[i]<kArray[0]){
kArray[0] = array[i];
//替换后需要再次维护最大堆
maxHeap(kArray,0);
}
}
for(int i :kArray)
System.out.println(i);
}
private void maxHeap(int[] kArray, int i) {
int left = 2*i+1;
int right = 2*i+2;
int largest = 0;
if(right<kArray.length&&kArray[left]>kArray[i]){
largest = left;
}else{
largest = i;
}
if(right<kArray.length&&kArray[right]>kArray[largest]){
largest = right;
}
if(largest!=i){
int temp = kArray[i];
kArray[i] = kArray[largest];
kArray[largest] = temp;
//重点!!根节点换成laregst可能会破坏最大堆结构
maxHeap(kArray,largest);
}
}
//建最大堆
private void buildMaxHeap(int[] kArray) {
for(int i=kArray.length/2;i>=0;i--){
maxHeap(kArray,i);
}
}
}