/*****************************************************************
题目:输入n个整数,找出其中最小的k个数。例如输入4,5,1,6,2,7,3,8这
8个数字,则最小的4个数字是1,2,3,4。
*****************************************************************/
#include<iostream>
#include<set>
#include<vector>
using namespace std;
void swap(int* pNum1, int* pNum2)
{
int nTemp = *pNum1;
*pNum1 = *pNum2;
*pNum2 = nTemp;
}
int partition(int* numbers, int start, int end)
{
if(numbers == NULL || start>end)
throw new std::exception("invalid input!\n");
int standard = numbers[end];
int small = start-1;
for(int i=start; i<end; ++i)
{
if(numbers[i] < numbers[end])
{
++small;
if(i != small)
swap(&numbers[i],&numbers[small]);
}
}
++small;
swap(&numbers[small], &numbers[end]);
return small;
}
//方法1
//按照第29题的思路,可以给予partition来解决这个问题
//如果基于数组的第k个数字来调整,使得第比第k个数字小的所有
//数字都位于数组的左边,比第k个数字大的所有数字都位于数组的
//右边。这样调整后,位于数组中左边的k个数字就是最小的k个数
//时间复杂度为O(N)
void GetLeastNumbers(int* input,int n, int* output, int k)
{
if(input == NULL || n<=0 || output == NULL || k<=0 || k>n)
throw std::exception("invalid question!");
int start = 0;
int end = n-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)
{
output[i] = input[i];
}
}
//方法2:特别适合处理海量数据
//用堆或者红黑树实现。先填满容器k个元素,后面的数字如果大于容器中最大值,、
//就将容器中最大值删除,加入新元素。
//这里采用multiset解决问题,它是由红黑树实现的
typedef multiset<int,greater<int>> intSet;
typedef multiset<int,greater<int>>::iterator setIterator;
void GetLeastNumbers(const vector<int>& data, intSet& leastNumbers,
int k)
{
leastNumbers.clear();
if(k<1 || data.size()<k) //输入无效
return;
vector<int>::const_iterator iter = data.begin();
for(;iter != data.end(); ++iter)
{
if((leastNumbers.size())<k)
leastNumbers.insert(*iter);
else
{
setIterator iterGreatest = leastNumber.begin();
if(*iter < *(leastNumbers.begin()))
{
leastNumbers.erase(iterGreatest);
leastNumbers.inset(*iter);
}
}
}
}
void test()
{
const int length = 8;
int input[length] = {4,5,1,6,2,7,3,8};
const int k = 4;
int output[k];
GetLeastNumbers(NULL,0,output,k);
for(int i=0; i<k; ++i)
{
printf("%d\t",output[i]);
}
}
int main()
{
try{
test();
}
catch(std::exception ex)
{
std::cerr<<ex.what();
}
return 0;
}
第一种方法复杂度第,但要改变输入的数据;而第二种方法不会改变输入的数据适用于n很大,k较小的问题
==参考剑指offer