题目链接:最小的K个数
思路:堆排序中每趟可以输出最小元素,所以,借助堆排序可以得到最小的K个数。
步骤:
1 创建无元素的ArrayList对象。
2 如果数组为空或者k不是正整数,则返回指向ArrayList对象的引用。
3 获取数组容量。如果数组容量小于k,则返回指向ArrayList对象的引用;如果数组容量是1且k是1即结果只有1个元素,则把该元素添加到ArrayList对象中,返回指向ArrayList对象的引用。
4 创建容量为len+1的新数组,使下标从1开始。
5 拷贝数组元素。
6 构造初始小顶堆。
7 k趟获取当前最小元素,并把该元素添加到ArrayList对象中。
8 返回指向ArrayList对象的引用。
Java代码:
1 import java.util.ArrayList;
2
3 public class Solution {
4 public ArrayList<Integer> GetLeastNumbers_Solution(int[] a, int k) {
5 // 创建ArrayList对象
6 ArrayList<Integer> arrayList = new ArrayList<Integer>();
7 // 如果数组为空或者k不是正整数
8 if (a == null || k <= 0) {
9 return arrayList;
10 }
11
12 // 获取数组容量
13 int len = a.length;
14 // 如果数组容量小于k
15 // 如果数组容量是1且k是1即结果只有1个元素
16 if (len < k) {
17 return arrayList;
18 }
19 else if (len == 1 && k == 1) {
20 arrayList.add(a[0]);
21 return arrayList;
22 }
23
24 // 创建容量为len+1的新数组,使下标从1开始
25 int[] arr = new int[len + 1];
26 // 拷贝数组元素
27 System.arraycopy(a, 0, arr, 1, len);
28
29 // 构造初始小顶堆
30 buildMinHeap(arr, len);
31 // k趟获取当前最小元素
32 for (int i = len, low = len - k + 1; i >= low; i--) {
33 arrayList.add(arr[1]);
34 arr[1] = arr[i];
35
36 // 把剩余的i-1个元素建成堆
37 adjustDown(arr, 1, i - 1);
38 }
39
40 return arrayList;
41 }
42
43 // 构造初始小顶堆
44 private void buildMinHeap(int[] arr, int len) {
45 // 反复调整堆
46 for (int i = len / 2; i >= 1; i--) {
47 adjustDown(arr, i, len);
48 }
49 }
50
51 // 把当前结点所在的子树建成小顶堆
52 private void adjustDown(int[] arr, int k, int len) {
53 // 暂存元素
54 arr[0] = arr[k];
55 // 沿着较小的子结点向下筛选
56 for (int i = 2 * k; i <= len; i *= 2) {
57 // 获取较小子结点的下标
58 if (i + 1 <= len && arr[i] > arr[i + 1]) {
59 i++;
60 }
61
62 // 筛选结束
63 if (arr[0] <= arr[i]) {
64 break;
65 } else {
66 // 把A[i]调整到双亲结点上
67 arr[k] = arr[i];
68 // 修改k值,以便继续向下筛选
69 k = i;
70 }
71 }
72
73 // 把元素放在最终位置上
74 arr[k] = arr[0];
75 }
76 }
参考资料