剑指Offer-40:最小的k个数
2018-03-09 15:28
260 查看
题目:
输入n个整数,找出其中最小的K个数。例子
例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。链接:
剑指Offer(第2版):P209思路标签:
算法:快排分区、堆排序数据结构:红黑树
解答:
1. 基于快排Partition函数的算法(时间复杂度:O(n))
基于快排算法中的Partition函数,使得比选中的数字小的数字都在它左边,比选中的数字大的数字都在它的右边。如果选中的数字的下标刚好是k-1,那么这个数字就是数组中的中位数;
如果它的下标大于k-1,那么中位数应该位于它的左边,继续在左边寻找;
如果它的下标小于k-1,那么中位数应该位于它的右边,继续在右边寻找。
利用递归实现,但是会修改输入数组的顺序,这里需要问清面试官。
class Solution { public: void swap(int &i, int &j) { if (i == j) return; int temp = i; i = j; j = temp; } int Partition(vector<int> &input, int start, int end) { if (input.empty() || start>end) return -1; int index = rand() % (end - start + 1) + start; swap(input[index], input[end]); int small = start - 1; for (index = start; index<end; ++index) { if (input[index] <= input[end]) { ++small; if (index != small) swap(input[index], input[small]); } } small++; swap(input[small], input[end]); return small; } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> result; if (input.empty() || k>input.size() || k <= 0) return result; int start = 0; int end = input.size() - 1; int index = Partition(input, start, end); while (index != (k - 1)) { if (index > (k - 1)) { end = index - 1; index = Partition(input, start, end); } else { start = index + 1; index = Partition(input, start, end); } } for (int i = 0; i<k; ++i) { result.push_back(input[i]); } return result; } };
2. 堆排序,适合处理海量数据(时间复杂度O(nlgk))
利用一个大小为k的数据容器来存储最小的k个数字,如果容器中的数字小于k个,那么直接将数据放入;如果容器中已经存在k个数字,则用待插入的整数和容器中的最大值进行比较,小于最大值则替换,否则输入下一个数字。
很明显利用最大堆的原理来进行求解。
可以直接利用STL中的set和multiset,二者是利用红黑树实现的。
class Solution { public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> result; int length = input.size(); if (input.empty() || k < 1 || length < k) return result; multiset<int, greater<int>> leastNumbers; //从大到小排序的set multiset<int, greater<int>>::iterator iterGreater; //定义迭代器 vector<int>::const_iterator iter = input.begin(); for (; iter != input.end(); ++iter) { if (leastNumbers.size() < k) leastNumbers.insert(*iter); else { iterGreater = leastNumbers.begin(); if (*iter < *(iterGreater)) { leastNumbers.erase(iterGreater); leastNumbers.insert(*iter); } } } for (iterGreater = leastNumbers.begin(); iterGreater != leastNumbers.end(); ++iterGreater) result.push_back(*iterGreater); return result; } };
C++相关
C++ STL set容器常用用法http://blog.csdn.net/cerberux/article/details/51774121
【C++ STL】Set和Multiset
<
4000
a href="https://www.cnblogs.com/ChinaHook/p/6985444.html">https://www.cnblogs.com/ChinaHook/p/6985444.html
相关文章推荐
- 【剑指offer】面试题40:最小的k个数
- 【剑指offer】面试题 40:最小的 k 个数
- 剑指offer面试题8:旋转数组的最小数字
- 旋转数组中的最小数字,剑指offer,P70 二分查找来实现O(logn)的查找
- 【剑指offer】面试题11:旋转数组的最小数字
- 剑指offer---旋转数组的最小数字
- 剑指offer----最小的k个数----java实现
- 《苦练算法》-剑指Offer- 三十二、把数组排成最小的数-python编写
- 剑指offer-定义栈实现栈最小元素的min函数
- 【剑指offer】旋转数字的最小数字
- 码农小汪-剑指Offer之30 -把数组排成最小的数(拼接字符串排序)
- 剑指offer - 把数组排成最小的数
- 剑指offer-面试题8.旋转数组的最小数字
- 剑指offer--旋转数组的最小数字
- 剑指offer 面试题40 数组中出现一次的两个数
- 剑指offer之旋转数组的最小数字
- 【剑指offer】 把数组排成最小的数(含完整代码与注解)
- 剑指offer之把数组排成最小的数
- 【剑指offer】6.旋转数组最小的数
- 剑指Offer之把数组排成最小的数