// 30 FindMinKNum.cpp : Defines the entry point for the console application.
//
/*****************************************************************************************************
* 找出数组中最小的K个数并输出
* 《剑指offer》面试题30:输入n个整数,找出其中最小的k个数。例如:输入4,5,1,6,2,7,3,8这8个数字,则最小的
4个数字为1,2,3,4.
* 思路1:对数组按从小到大进行排序,最前面的K个数即为最小的K个数。时间复杂度O(nlogn)。
思路2:利用快速排序的Partition函数,找出第k小的数a,我们知道此时第k小的数的左边均小于a,右边均大于a,
此时,直接输出数组的前k个数即可。时间复杂度O(n),可以修改输入的数组时可用。此方法的实现参见上篇
《在O(n)时间内找到数组中任意第k小的数》
思路3:可以先创建一个大小为k的数据容器来存储最小的k个数字,接下来每次从输入的n个整数中读入一个数。
如果容器中已有的数字少于k个,则直接把这次读入的数据放入容器之中;
如果容器已满,找出容器中k个数字的最大值,然后拿这次待插入的整数与其进行比较。如果插入的值比当前已有
的最大值大,那么这个数不可能是最小的k个整数之一,于是可以抛弃这个数。如果带插入的值小于当前已有最大
数,则删除容易中已有的最大数,并插入这个带插入的值。重复上述过程。由于每次都需要找到k个整数中最大的
数字,很容易想到利用最大堆来实现上述过程。
******************************************************************************************************/
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
//#include <map>
#include <set>
using namespace std;
class Compare
{
public:
bool operator()(const int& a, const int& b)
{
return (a-b)>0;
}
};
bool FindMinKNum(ifstream& ifs, const int& k, multiset<int, Compare>& MinKNum);
bool FindMinKNum(int a[], const int& Len, const int& k, multiset<int, Compare>& MinKNum);
int _tmain(int argc, _TCHAR* argv[])
{
/*map<string, int> students;
pair<string, int> stu1;
pair<string, int> stu2;
stu1 = make_pair("li", 80);
stu2 = make_pair("chen", 70);
students.insert(stu1);
students.insert(stu2);
map<string, int>::iterator i;
for(i=students.begin(); i!=students.end(); i++)
cout<<(*i).first<<" "<<(*i).second<<endl;*/
/*
int a[] = {4,5,1,6,2,7,3,8};
multiset<int, Compare> MinKNum;
multiset<int, Compare>::iterator IterBeg;
multiset<int, Compare>::iterator IterEnd;
FindMinKNum(a, 8, 4, MinKNum);
IterBeg = MinKNum.begin();
IterEnd = MinKNum.end();
for(; IterBeg!=IterEnd; IterBeg++)
cout<<(*IterBeg)<<" ";
*/
ifstream ifs(_T("data.txt"));
multiset<int, Compare> MinKNum;
multiset<int, Compare>::iterator IterBeg;
multiset<int, Compare>::iterator IterEnd;
FindMinKNum(ifs, 10, MinKNum);
IterBeg = MinKNum.begin();
IterEnd = MinKNum.end();
for(; IterBeg!=IterEnd; IterBeg++)
cout<<(*IterBeg)<<" ";
while(true);
return 0;
}
/**************************************************************************************
* Author: sky
* Functiuon: FindMinKNum
* Description: 找出给定文件中最小的k个数
* Access Level: NULL
* Input: ifs:输入文件流
k: 最小的k个数
* Output: MinKNum:存储找出的最小的k个数
* Return: false/true
**************************************************************************************/
bool FindMinKNum(ifstream& ifs, const int& k, multiset<int, Compare>& MinKNum)
{
multiset<int, Compare>::iterator iter;
int data; // 存储每次从文件读取到的数据
int count = 0; // 记录muliset中元素的个数
ifs>>data;
while(ifs.good())
{
if(k > count)
{
MinKNum.insert(data);
count++;
}
else
{
iter = MinKNum.begin();
if((*iter) > data)
{
MinKNum.erase(iter);
MinKNum.insert(data);
}
}
ifs>>data;
}
return true;
}
/**************************************************************************************
* Author: sky
* Functiuon: FindMinKNum
* Description: 找出给定数组中最小的k个数
* Access Level: NULL
* Input: a: 输入数组
k: 最小的k个数
* Output: MinKNum:存储找出的最小的k个数
* Return: false/true
**************************************************************************************/
bool FindMinKNum(int* a, const int& Len, const int& k, multiset<int, Compare>& MinKNum)
{
if((NULL==a) || (k>Len))
return false;
multiset<int, Compare>::iterator iter;
int i = 0;
for(i=0; i!=Len; i++)
{
if(i < k)
MinKNum.insert(a[i]);
else
{
iter = MinKNum.begin();
if((*iter) > a[i])
{
MinKNum.erase(iter);
MinKNum.insert(a[i]);
}
}
}
return true;
}
输入文件:
输出结果: