最小的k个数
来源:互联网 发布:南山软件产业基地图片 编辑:程序博客网 时间:2024/06/06 13:04
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
题解
1. 全排序
直接sort函数,返回前k个
时间复杂度O(nlogn)
2. 冒泡或选择排序
时间复杂度O(k*n)
class Solution {public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> haha; if(k > input.size()) return haha; for(int i = 0; i < k; i++){ for(int j = i + 1; j < input.size(); j++){ if(input[i] > input[j]) swap(input[i], input[j]); } haha.push_back(input[i]); } return haha; }};
3. 堆排序
维护容量为k的最大堆
- 用容量为k的最大堆存储最先遍历到的k个数,同样假设它们即是最小的k个数
- 遍历剩余n-k个数。假设每一次遍历到的新的元素的值为x,把x与堆顶元素kmax比较:如果x < kmax,用x替换kmax,然后更新堆(用时logk);否则不更新堆。
时间复杂度:O(k+(n-k)*logk)=O(n*logk)
class Solution {public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { int len = input.size(); if(len <= 0 || k <= 0 || k > len) return vector<int>(); vector<int> haha(input.begin(), input.begin() + k); makeHeap(haha); for(int i = k; i < len; i++){ if(input[i] < haha[0]){ haha[0] = input[i]; adjustHeap(haha, 0); } } return haha; }private: void adjustHeap(vector<int>& input, int i){ int len = input.size(); if(i > len / 2 - 1) return; //叶节点 int left = 2 * i + 1, right = left + 1; int max = i; if(left < len && input[max] < input[left]) max = left; if(right < len && input[max] < input[right]) max = right; if(max != i){ swap(input[max], input[i]); adjustHeap(input, max); } } void makeHeap(vector<int>& input){ for(int i = input.size() / 2 - 1; i >= 0; i--){ adjustHeap(input, i); } }};
4. 快排思想
- 选取S中一个元素作为枢纽元v,将集合S-{v}分割成S1和S2,就像快速排序那样
- 如果k <= |S1|,那么第k个最小元素必然在S1中,返回QuickSelect(S1, k)。
- 如果k = 1 + |S1|,那么枢纽元素就是第k个最小元素,即找到,直接返回它。
- 否则,这第k个最小元素就在S2中,即S2中的第(k - |S1| - 1)个最小元素,我们递归调用并返回QuickSelect(S2, k - |S1| - 1)。
class Solution {public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> haha; if(k > input.size()) return haha; QuickSelect(input, 0, input.size() - 1, k); for(int i = 0; i < k; i++){ haha.push_back(input[i]); } return haha; }private: void QuickSelect(vector<int>& input, int left, int right, int k){ if(k <= 0 || left + k > right) return; int pivot = (left + right) >> 1; swap(input[left], input[pivot]); //注意特殊用例,如(1,2),i应指向1 int i = left, j = right; while(i < j){ //先让j走保证i指向不大于pivot的值 while(i < j && input[j] > input[left]) j--; while(i < j && input[i] <= input[left]) i++; if(i < j){ swap(input[i], input[j]); } } swap(input[left], input[i]); QuickSelect(input, i + 1, right, k - i - 1 + left); QuickSelect(input, left, i - 1, k); //用i-1而不是i,防止如(1,1,1)的死循环 }};
0 0
- 最小的K个数
- 最小的K个数
- 最小的K个数
- 最小的k个数
- 最小的k个数
- 最小的k个数
- 最小的k个数
- 最小的k个数
- 最小的k个数
- 最小的K个数
- 最小的k个数
- 最小的K个数
- 最小的K个数
- 最小的K个数
- 最小的K个数
- 最小的K个数
- 最小的k个数
- 最小的k个数
- 【一步步学OpenGL 26】-《法线贴图》
- 3、uboot源码——主Makefile分析
- dubbo学习过程、使用经验分享及实现原理简单介绍
- 大数据IMF传奇行动绝密课程第85课:基于HDFS的SparkStreaming案例实战和内幕源码解密
- leetcode217. Contains Duplicate
- 最小的k个数
- G
- 使用Pull和SAX解析XML格式数据
- (OK) porting MPTCP to LineageOS-14.1-kiwi (Android-7.1.1,运行在Huawei honor 5x) for VirtualBox
- 如何生成验证码(方法一)
- 前端列表筛选效果
- poj 3259 (SPFA,求是否有负权回路)
- POJ 2718-Smallest Difference [dfs] 《挑战程序设计竞赛》2.1
- 面向对象的理解