剑指Offer 最小的K个数

Posted wjq2017

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer 最小的K个数相关的知识,希望对你有一定的参考价值。

  题目链接:最小的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 }

  

  参考资料

  [编程题]最小的K个数

以上是关于剑指Offer 最小的K个数的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer--40最小的k个数

剑指offer---最小的K个数

剑指 Offer 40. 最小的k个数

最小的K个数-剑指Offer

剑指offer:最小k个数

剑指 Offer 40. 最小的k个数