剑指 Offer 40. 最小的k个数

Posted lxy

tags:

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

题目链接:剑指 Offer 40. 最小的k个数

方法:排序

解题思路

  1. 基于比较的排序,最低时间复杂度为\\(O(nlogn)\\),空间复杂度为\\(O(1)\\)
  2. 哈希计数,时间复杂度为\\(O(n)\\),但需要额外的空间。

代码

// 基于比较的排序
class Solution 
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) 
        vector<int> ans(k);
        sort(arr.begin(), arr.end());
        for (int i = 0; i < k; i ++ ) 
            ans[i] = arr[i];
        
        return ans;
    
;

// hash计数
class Solution 
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) 
        int cnt[10001] = 0;
        vector<int> ans(k);
        for (int i = 0; i < arr.size(); i ++ ) 
            cnt[arr[i]] ++ ;
        
        for (int i = 0, j = 0; i < 10001 && j < k; i ++ ) 
            while (cnt[i] > 0 && j < k) 
                ans[j ++] = i;
                cnt[i] -- ;
            
        
        return ans;
    
;

剑指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 40. 最小的k个数的主要内容,如果未能解决你的问题,请参考以下文章

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

剑指 Offer 40. 最小的k个数

剑指 Offer 40. 最小的k个数

[剑指 Offer 40]. 最小的 k 个数

[剑指 Offer 40]. 最小的 k 个数

「LeetCode」剑指 Offer 40. 最小的k个数