zoukankan      html  css  js  c++  java
  • 查找数组中最小的k 个元素

    输入n 个整数,输出其中最小的k 个。

    例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。

    经典的TopK问题,因为需要最小的K个元素,所以只需创建并维持一个拥有K个元素的最大堆即可。

    创建一个拥有K个元素的最大堆的代码为:

     1 void CreateMaxHeap(int *MaxHeap, int K)
     2 {
     3     assert (MaxHeap != NULL);
     4 
     5     assert (K > 0);
     6 
     7     // 从最后一个有子孩子的节点开始往下调整,一直到根节点,则这个最大堆就创建好了
     8     for (int i = (K >> 1) - 1; i >= 0; --i)
     9     {
    10         MaxHeapFixDown (MaxHeap, i, K);
    11     }
    12 }

    向下调整最大堆得函数代码为:

     1 void MaxHeapFixDown(int *MaxHeap, int l, int K)
     2 {
     3     assert (MaxHeap != NULL);
     4 
     5     assert (l >= 0);
     6 
     7     assert (l < K);
     8 
     9     int nTemp = MaxHeap[l];
    10     int i = l;
    11     int j = 2 * i + 1;
    12 
    13     while (j < K)
    14     {
    15         if (((j + 1) < K) && (MaxHeap[j+1] > MaxHeap[j]))
    16         {
    17             // 获取两个子孩子中值最大的那个
    18             ++j;
    19         }
    20 
    21         if (MaxHeap[j] <= nTemp)
    22         {
    23             // 如果最大的子孩子都小与nTemp,则nTemp的正确位置就是这两个孩子父亲的位置
    24             break;
    25         }
    26 
    27         // 大值往上冒
    28         MaxHeap[i] = MaxHeap[j];
    29         i = j;
    30         j = 2 * i + 1;
    31     }
    32 
    33     // 确定nTemp的正确位置
    34     MaxHeap[i] = nTemp;
    35 }

      基于上,我们只需将数组的前K个元素调整成最大堆,然后从第K+1个元素开始与最大堆的根节点比较(最大堆的根节点是堆中的最大值),若比最大值小,则需将这个元素与堆的根节点交换位置,然后调整这个最大堆,反之则不需做任何处理,一直到数组中第N个元素。最后数组中最小的K个元素就是数组的前K个元素,直接将其输出即可。

      基于上述分析,获取最小K个元素的代码如下:

     1 void GetKMinNumber(int *a, int N, int K)
     2 {
     3     assert (a != NULL);
     4 
     5     assert (K > 0);
     6 
     7     assert (K <= N);
     8 
     9     if (K == N)
    10     {
    11         // 最小的K歌元素就保存在数组a的前K个数据块中
    12         cout << "最小的 " << K << " 个元素为: ";
    13         for (int i = 0; i < K; ++i)
    14         {
    15             cout << a[i] << " ";
    16         }
    17 
    18         cout << endl;
    19 
    20         return;
    21     }
    22 
    23     // 创建一个最大堆
    24     CreateMaxHeap (a, K);
    25 
    26     for (int i = K; i < N; ++i)
    27     {
    28         if (a[i] < a[0])
    29         {
    30             Swap (a[i], a[0]);
    31 
    32             // 更新一个元素后就要维护这个堆,使其保持为最大堆
    33             MaxHeapFixDown (a, 0, K);
    34         }
    35     }
    36 
    37     // 最小的K歌元素就保存在数组a的前K个数据块中
    38     cout << "最小的 " << K << " 个元素为: ";
    39     for (int i = 0; i < K; ++i)
    40     {
    41         cout << a[i] << " ";
    42     }
    43 
    44     cout << endl;
    45 }

      给出一个测试结果如下:

  • 相关阅读:
    Apollo的Oracle适配改动
    尝试Java,从入门到Kotlin(下)
    尝试Java,从入门到Kotlin(上)
    RabbitMQ权限控制原理
    一文彻底掌握二叉查找树(多组动图)(史上最全总结)
    图解:深度优先搜索与广度优先搜索及其六大应用
    图解:如何理解与实现散列表
    图解:什么是“图”?
    查找算法系列文(一)一文入门二叉树
    线性表(数组、链表、队列、栈)详细总结
  • 原文地址:https://www.cnblogs.com/ldjhust/p/3051969.html
Copyright © 2011-2022 走看看