最小的K个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
方法一
基于随机快排思想,基于数组的第k个数字来调整,则使得比第k个数字小的所有数字都在数组的左边,比k大的数字都在数组的右边。这样调整之后位于数组中左边的k个数字就是最小的k个数字。
/**
* 利用快排思想,时间复杂度O(n)
* @param input
* @param k
* @return
*/
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(input == null || input.length == 0 || k > input.length || k <= 0) {
return list;
}
int start = 0;
int end = input.length - 1;
int index = Partition(input, start, end);
while(index != k - 1) {
if(index < (k - 1)) {
start = index + 1;
index = Partition(input, start, end);
}
else {
end = index - 1;
index = Partition(input, start, end);
}
}
for (int i = 0; i < k; i++) {
list.add(input[i]);
}
return list;
}
public int Partition(int[] elem, int low, int high) {
int pivotkey = elem[low];
while(low < high) {
while((low < high) && elem[high] > pivotkey) {
high--;
}
swap(elem, low, high);
while((low < high) && elem[low] <= pivotkey) {
low++;
}
swap(elem, low, high);
}
return low;
}
public void swap(int[] elem, int i, int j) {
int temp = elem[i];
elem[i] = elem[j];
elem[j] = temp;
}
方法二
利用最大堆的思想,创建一个大小为k的最大堆用来存储最小的k个数字。接下来每次从输入的n个整数中读入一个数。如果最大堆中已有的数字小于k个,直接将这个整数存放进去。如果已经满了,应该替换最大堆中最大的数字。而根据最大堆的特性,根节点的值比所有节点都大,所以可以实现O(1)的最大数的查找。不过在插入删除时需要O(logk)的时间来完成。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public ArrayList<Integer> GetLeastNumbers_Solution_2(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(input == null || input.length == 0 || k > input.length || k <= 0) {
return list;
}
//创建一个最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11, new Comparator<Integer>() {
public int compare(Integer i1, Integer i2) {
return i2.compareTo(i1);
}
});
for (int i = 0; i < input.length; i++) {
if(maxHeap.size() < k) {
maxHeap.add(input[i]);
}
else {
if(maxHeap.peek() <= input[i]) {
continue;
}
else {
maxHeap.poll();
maxHeap.add(input[i]);
}
}
}
for (Integer integer : maxHeap) {
list.add(integer);
}
return list;
}