文章目录

  • 题目描述:
  • 解题思路:
    • 1、完全排序O(n*logn)
    • 2、部分选择排序O(n*k)
    • 3、最大堆O(nlogk)
    • 4、基于快排的算法O(n)

题目描述:

  输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

解题思路:

1、完全排序O(n*logn)

  没什么好说的,先排序再选择前K个数。

class Solution {public:vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {int sz = input.size();vector<int> vec;if (sz == 0 || k <= 0 || sz < k)return vec;sort(input.begin(), input.end());for (int i = 0; i < k; ++i)vec.push_back(input[i]);return vec;}
};

2、部分选择排序O(n*k)

  因为只需要前K个数,所以不用排序全部的数,只需要通过K次排序找到K个最小的数即可。

class Solution {public:vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {int sz = input.size();vector<int> vec;if (sz == 0 || k <= 0 || sz < k)return vec;for (int i = 0; i < k; ++i){for (int j = i + 1; j < sz; ++j){if (input[i] > input[j])swap(input[i], input[j]);}vec.push_back(input[i]);}return vec;}
};

3、最大堆O(nlogk)

1. 首先选取前K个数建立最大堆(根结点值大于左右结点值)。

2. 此后,每次从原数组中取一个元素与根进行比较,如果大于根结点的元素,忽视之,取下一个数组元素继续该过程;如果小于根结点的元素,则将其加入最大堆,并进行堆调整,将根元素移动到最后再删除,即保证最大堆中的元素仍然是排名前K的数,且根元素仍然最大。

class Solution {public:vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {int sz = input.size();vector<int> vec;if (sz == 0 || k <= 0 || sz < k)return vec;for (int i = 0; i < k; ++i)vec.push_back(input[i]);// 以数组前k个元素建立初始的最大堆make_heap(vec.begin(), vec.end(), less<int>());for (int i = k; i < sz; ++i){if (input[i] > vec.front()) // 如果接下来的元素比堆顶元素大,直接跳过continue;else // 如果接下来的元素比堆顶元素小,则调整堆{vec.push_back(input[i]);// 添加新元素调整堆push_heap(vec.begin(), vec.end());// 将堆顶元素调整到最后pop_heap(vec.begin(), vec.end());// 删除最后那个元素vec.pop_back();}}// 以上方法得到的只是求了TopK,但是并未排序,所以使用sort_heap排序一下sort_heap(vec.begin(), vec.end());return vec;}
};

【该算法有两个明显的优点】:

  • 没有修改输入的数据(代码中的变量data)。我们每次只是从data中读入数字,所有的写操作都是在容器leastNumbers中进行的。

  • 该算法适合海量数据的输入,不需要将数据一次性全部载入内存

4、基于快排的算法O(n)

1. 利用快速排序划分的思想,每一次划分就会有一个数字位于以数组从小到达排列的的最终位置location(假设下标从1开始);

2. 位于index左边的数字都小于location对应的值,右边都大于location指向的值;所以,当location> k时,表示k个最小数字一定在location的左边,此时,只需要对location的左边进行划分即可;

3. 当location< k 时,说明location及location左边数字还没能满足k个数字,需要继续对location右边进行划分

4. 当index = k 时,说明已划分完。

class Solution {public:int partition(vector<int>& arr, int low, int high){int pivot = arr[high]; // 选最后一个元素作为枢纽元int location = low; // location放置的是最新的比枢纽元小的元素for (int i = low; i < high; i++) // 比枢纽元小的元素依次放在前半部分if (arr[i] < pivot)swap(arr[i], arr[location++]); // 移动locationswap(arr[high], arr[location]); // 最后交换的是arr[high],不是pivotreturn location;}void quick_sort(vector<int>& arr, int low, int high, int k){if (low < high){int middle = partition(arr, low, high);// 如果middle大于k-1,则说明arr[middle]右边的元素都大于k,于是只递归arr[low, middle-1]即可if (middle > k - 1)quick_sort(arr, low, middle-1, k);// 如果middle小于k-1,则说明arr[middle]左边的元素都小于k,于是只递归arr[middle+1, high]即可if (middle < k - 1)quick_sort(arr, middle+1, high, k);// 如果middle等于k-1说明前k个元素已经找到if (middle == k - 1)return;}}vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {int sz = input.size();vector<int> vec;if (sz == 0 || k <= 0 || sz < k)return vec;quick_sort(input, 0, input.size() - 1, k);for (int i = 0; i < k; ++i){vec.push_back(input[i]);}return vec;}
};

28、最小的k个数(TopK)相关推荐

  1. 剑指offer 40.最小的 K 个数 python代码

    题目 寻找数组中的最小的k个数,也叫topk问题. 牛客网测试地址 注意: 牛客网的提交需要将最终的结果排序 思路 快速排序的 partition() 方法,会返回一个整数 j 使得 a[l-j-1] ...

  2. 【剑指offer-Java版】30最小的K个数

    最小的K个数: 思路一:类似于第29题,直接进行Partion,直到返回值未K – 缺点是需要修改输入的数据 思路二:维护一个大顶堆,然后遍历一次给定数组 如果当前堆元素小于K个 那么直接将当前元素加 ...

  3. 九度 1371 最小的K个数

    题目描述:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 输入: 每个测试案例包括2行:第一行为2个整数n,k(1<= ...

  4. 海量数据中,寻找最小的k个数。

    维护k个元素的最大堆,即用容量为k的最大堆存储最小的k个数,k1设为大顶堆中最大元素.遍历一次数列,n,每次遍历一个元素x,与堆顶元素比 较,x<kmax,更新堆,否则不更新堆. 1 // 海量 ...

  5. C#刷剑指Offer | 【常考题】最小的k个数

    [C#刷题]| 作者 / Edison Zhou 这是EdisonTalk的第299篇学习分享 我们来用之前学到的数据结构知识来刷<剑指Offer>的一些核心题目(精选了其中30+道题目) ...

  6. 【算法】数组与矩阵问题——找到无序数组中最小的k个数

    1 /** 2 * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) 3 * 过程: 4 * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 5 * 在堆里的k个元素中堆顶 ...

  7. 面试题30.最小的k个数

    题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8 这8个数字,则最小的四个数字为1,2,3,4, 这道题是典型的TopK问题,剑指Offer提供了两种方法来实现,一种方 ...

  8. 最小的K个数(手写大顶堆和用优先级队列比较)

    题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 题目链接:https://www.nowcoder.com/prac ...

  9. 程序员编程艺术:第三章、寻找最小的k个数

    程序员编程艺术:第三章.寻找最小的k个数 作者:July. 时间:二零一一年四月二十八日. 致谢:litaoye, strugglever,yansha,luuillu,Sorehead,及狂想曲创作 ...

最新文章

  1. Pytorch+LSTM+AI自动写诗实战
  2. 美团第一位前端工程师竟是转行程序员!关于他的10年技术生涯
  3. kibana 报错 server is not ready yet 可能的原因
  4. ROS调用本地摄像头数据并在rviz里显示
  5. AtCoder AGC030C Coloring Torus (构造)
  6. java 图像倾斜角度计算_【干货】无人机航测倾斜实景三维建模进行土方计算(基于Smart3D全面讲解)...
  7. sizeof你真的弄明白了吗?
  8. 什么叫python代码的优化_优化Python代码
  9. springboot 上传文件解析入库_springboot上传文件的访问
  10. Halcon 圆形标定板标定基本流程-标定助手操作
  11. redis安装及使用
  12. 【Webcam设计】利用底层V4L2+OPENCV进行图像处理以及移植策略
  13. 吉比特H2-3光猫破解超级密码
  14. python selenium下载图片_selenium下载图片(原图)
  15. CS和BS 到底是什么
  16. Word创建层级目录
  17. 方法论-5W2H七问分析法
  18. sap销售发货的流程_SAP标准业务流程-销售订单处理
  19. win10网络适配器不见了_Win10网络适配器消失不见了怎么办?,爱纯净官网
  20. 永恒之蓝ms17_010漏洞利用攻击

热门文章

  1. 这样制作一个Android输入法开发微信斗图APP,斗图就再也没输过!
  2. Matlab 实现磁测数据日变改正
  3. elementUI使用vue-direction-key实现键盘上下左右bug解决办法
  4. 工资条打印 Excel操作
  5. 3.2 安卓触摸事件
  6. Python教材(数据分析、数据挖掘与可视化)——第四章课后习题
  7. PhoneWindowManager
  8. PluginOK中间件小程序家族不断壮大
  9. vue中的三个缩写指令
  10. android模拟器无法拍照,android – 任何模拟器的相机无法正常工作