题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
 
思路:
解法1:对于小规模数据,可以采用类似前题的快速排序思路,pivot之前的点都是比它小的,之后的点都是比它大的。不管是找中位数还是找前k大,前k小,都可以使用这个方法,平均复杂度是O(N),但是最坏时间复杂度是O(N*N)。这样得到最后k个数是没有进行排序的,所以降低了时间复杂度。
这里需要注意idx初值不该设为0,因为找最小的0个数的时候idx = lo = 0;就不会进入循环当中,所以应该注意39行和50行。这题有个大坑就是k的讨论,k可能小于等于0,也可能大于size,所以必须要进行讨论。
这种方法会对输入的数组进行改变,所以应该要明确告诉面试官这样是否允许。而且这种做法适合小规模数据。
 
 class Solution {
public:
int partition(vector<int> &input,int lo,int hi){
int pos = lo + rand() % (hi - lo + );
int pivot = input[pos];
swap(input[lo],input[pos]);
while(lo < hi){
while(lo < hi){
if(input[hi] > pivot){
--hi;
}
else{
input[lo] = input[hi];
++lo;
break;
}
}
while(lo < hi){
if(input[lo] < pivot){
++lo;
}
else{
input[hi] = input[lo];
--hi;
break;
}
}
}
input[lo] = pivot;
return lo;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
if(input.empty() || k > input.size() || k <= ){
return {};
}
vector<int> result;
int lo = ,hi = input.size() - ;
int idx ;
idx = partition(input,lo,hi);//
int target = k - ;
while(idx != target){ if(idx < target){
lo = idx + ; }
else if(idx > target){
hi = idx - ;
}
idx = partition(input,lo,hi);
}
for(int i = ;i < k;++i){
result.push_back(input[i]);
}
return result;
}
};

第二种方法:

解法2:O(nlogk)的算法,特别适合处理海量数据。

priority_queue加入和删除操作都是O(logk),top操作是O(1)。默认top的是最大元素。优先级队列本质是基于vector实现的最大堆,因为vector通过下标访问数组,所以top操作复杂度是O(1)的;

STL的set和map还有就是multise和multimap都是基于红黑树实现的,begin是最小元素,即基于最小堆实现的,只有自己写一个仿函数就可以得到最大堆,注意就重载()就行了,stack和queue都是基于deque。红黑树中查找、删除和插入操作的时间复杂度都是O(logk)。

如果要使用仿函数要引入头文件functional。才可以使用greater<int>。

但它是如何保证一棵n个结点的红黑树的高度始终保持在logn的呢?这就引出了红黑树的5个性质:

  1. 每个结点要么是红的要么是黑的。
  2. 根结点是黑的。
  3. 每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。
  4. 如果一个结点是红的,那么它的两个儿子都是黑的。
  5. 对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。
#include<iostream>
#include<vector>
#include<string>
#include <cstdio>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
template<typename T>
struct greater{
bool operator() (const T &a, const T &b) {
return a > b;
}
}; int main() {
multiset<int,greater<int>> hashSet;
for (int i = ; i < ; ++i) {//输入1,3,55,4
int a = ;
cin >> a;
hashSet.insert(a);
}
multiset<int>::iterator iter = hashSet.begin();//得到55
cout << *iter << endl;
system("pause");
}

仿函数最大set

#include<iostream>
#include<vector>
#include<set>
#include<functional>
using namespace std;
int main() {
multiset<int,greater<int>> hashSet;
for (int i = ; i < ; ++i) {//输入1,3,55,4
int a = ;
cin >> a;
hashSet.insert(a);
}
multiset<int>::iterator iter = hashSet.begin();//得到55
cout << *iter << endl;
system("pause");
}

使用functional

class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.empty() || k <= || k > input.size()){
return result;
}
multiset<int,greater<int>> hashSet;
multiset<int,greater<int>>::iterator iter = hashSet.begin();
for(int i = ;i < input.size();++i){
iter = hashSet.begin();
if(hashSet.size() < k){
hashSet.insert(input[i]);
}
else{
if(*iter > input[i]){
hashSet.erase(*iter);
hashSet.insert(input[i]);
}
}
}
iter = hashSet.begin();
for(iter;iter != hashSet.end();++iter){
result.push_back(*iter);
}
return result;
}
};

解法3:

使用priority_queue实现最大堆。(默认是最大堆,即top等于最大的元素,降序);

底层容器是vector实现的最大堆(stl源码)

模板:priority_queue<int,vector<int>,greater<int>>,升序,最小堆

class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result;
if(input.empty() || k <= || k > input.size()){
return result;
}
priority_queue<int> q;
for(int i = ;i < input.size();++i){
if(q.size() < k){
q.push(input[i]);
}
else{
if(q.top() > input[i]){
q.pop();
q.push(input[i]);
}
}
}
for(int i = ;i < k;++i){
result.push_back(q.top());
q.pop();
}
return result;
}
};

28 最小的K个数的更多相关文章

  1. 【面试题030】最小的k个数

    [面试题030]最小的k个数 题目:     输入n个整数,找出其中最小的k个数.     例如输入4.5.1.6.2.7.3.8这8个字,则其中最小的4个数字是1.2.3.4.     思路一:   ...

  2. 29.最小的K个数

    题目描述:   输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 思路分析:   利用快速排序的partition函数,par ...

  3. 剑指Offer面试题:27.最小的k个数

    一.题目:最小的k个数 题目:输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 这道题是典型的TopK问题,其最简单的思路莫过于 ...

  4. 算法练习:寻找最小的k个数

    参考July的文章:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数题目描述:查找最小的k个元素题目:输入n个整数,输出其中 ...

  5. 剑指Offer:面试题30——最小的k个数(java实现)

    问题描述: 输入n个整数,找出其中最小的k个数 思路1: 先排序,再取前k个 时间复杂度O(nlogn) 下面给出快排序的代码(基于下面Partition函数的方法) public void Quic ...

  6. 输入一个数组,求最小的K个数

    被这道题困了好久,看了剑指Offer才知道OJ上的要求有点迷惑性. 题目: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 一 ...

  7. 1046: 最小的K个数

    1046: 最小的K个数 时间限制: 1 Sec  内存限制: 128 MB提交: 233  解决: 200[提交][状态][讨论版] 题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1 ...

  8. 最小的K个数:用快排的思想去解相关问题

    实现快速排序算法的关键在于先在数组中选择一个数字,接下来把数组中的数字分为两部分,比选择的数字小的数字移到数组的左边,比选择的数字大的数字移到数组的右边. 这个函数可以如下实现: int Partit ...

  9. 剑指offer面试题30:最小的k个数

    一.题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 二.解题思路 1.思路1 首先对数组进行排序,然后取出前k个数 ...

随机推荐

  1. elasticsearch ik解析器

    ik解析器 1.      ik解析器 The IK Analysis plugin integrates Lucene IK analyzer (http://code.google.com/p/i ...

  2. java 8 list的stream操作 list中的对象中的某一个成员取出转为该成员的list,以及对象过滤,筛选某个属性后的成员

    取成员属性list List<String> configList = codeEntityList.stream().map(t -> t.getName()).distinct( ...

  3. VS中编码格式的问题(待总结)

    今天又遇到这样的事情了,VS中代码明明是正确的,却报某个变量未定义.百思不得解,前面增加了一个换行之后,竟然又神奇般的复原了. 最后确认是编码格式的问题,后来把有问题的那部分代码粘贴到微软的" ...

  4. 【PAT甲级】1001 A+B Format (20 分)

    题意:给两个整数a,b,计算a+b的值并每三位用逗号隔开输出(−1e6​​≤a,b≤1e6​​) AAAAAccepted code: #include<bits/stdc++.h> us ...

  5. text-align:justify 失效问题。

    text-align:justify 失效问题. <div class="fmlist_left"> <p> <span> 品名 <i c ...

  6. #P4770 [NOI2018]你的名字 的题解

    题目背景 实力强大的小A 被选为了ION2018 的出题人,现在他需要解决题目的命名问题. 题目描述 小A 被选为了ION2018 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外 ...

  7. [ DLPytorch ] 文本分类&图像增强

    图像增强 图像增广(image augmentation)技术通过对训练图像做一系列随机改变,来产生相似但又不同的训练样本,从而扩大训练数据集的规模.图像增广的另一种解释是,随机改变训练样本可以降低模 ...

  8. css简单整理

    style1.css /*统一设置h1.h2.a标签的样式*/ h1,h2,a{ color: aqua; font-size: 50px; } /*如果h1.h2没有上面的单独设置样式那么就会继承b ...

  9. 解决fastjson反序列化日期0000-00-00失败的方案

    解决fastjson反序列化日期0000-00-00失败的方案 22 Jul 2016 一.案例场景复原 示例场景里涉及两个class:TestDemo.java, DateBeanDemo.java ...

  10. IP地址,子网掩码,网段表示法,默认网关,DNS服务器详解,DNS域名设计

    本文参考:<计算机网络: IP地址,子网掩码,网段表示法,默认网关,DNS服务器详解> IP地址 概述 计算机要实现网络通信,就必须要有一个用于快速定位的网络地址.IP地址就是计算机在网络 ...