题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
解答:
一种比较常见的思路就是先排序后取出前k位数字,这其中有各类排序算法都适用。比如冒泡排序,每一次遍历结束都可以定位一个最小值,这样就只需要k次遍历。
另一种思路是利用大根堆这种结构,先把前k位数字建立一个大根堆,然后对后n-k个数依次遍历。如果当前数值小于堆顶的值则替换堆顶的值,然后对大根堆做向下调整。
public class Q_29 {
public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if (k > input.length || k == 0) {
return list;
}
int len = input.length;
creatBigHeap(input, k);//建立大根堆
for (int i = k; i < len; i++) {
if (input[i] < input[0]) {
int tmp = input[i];
input[k] = input[0];
input[0] = tmp;
ajustDown(input, 1, k);
}
}
for (int j = 0; j < k; j++) {
list.add(input[j]);
}
return list;
}
public int[] creatBigHeap(int[] A, int len) {
for (int i = A.length / 2; i > 0; i--) {
ajustDown(A, i, len);
}
return A;
}
private void ajustDown(int[] a, int i, int length) {//用递归的方法向下调整
if (i * 2 <= length) {
int tmp = a[i * 2 - 1];
if (a[i - 1] < a[i * 2 - 1]) {
if (i * 2 + 1 <= length && a[i * 2 - 1] < a[i * 2]) {
tmp = a[i * 2];
a[i * 2] = a[i - 1];
a[i - 1] = tmp;
ajustDown(a, i * 2 + 1, length);
} else {
a[i * 2 - 1] = a[i - 1];
a[i - 1] = tmp;
ajustDown(a, i * 2, length);
}
} else {
if (i * 2 + 1 <= length && a[i - 1] < a[i * 2]) {
tmp = a[i * 2];
a[i * 2] = a[i - 1];
a[i - 1] = tmp;
ajustDown(a, i * 2 + 1, length);
}
}
}
}
public static void main(String[] args) {
int[] a = {53, 17, 78, 9, 45, 65, 87, 32};
System.out.println(new Q_29().GetLeastNumbers_Solution(a, 4));
}}

京公网安备 11010502036488号