题目描述
输入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)); }
}