題目:
輸入n個整數,找出其中最小的k個數。例如輸入4、5、1、6、2、7、3、8這8個數字,則最小的4個數字是1、2、3、4。
最簡單的思路:將輸入的n個整數排序,排序之後位於最前面的k個數就是最小的k個數。時間複雜度O(nlogn)。
另一種思路:基於快速排序Partition函數。
基於數組的第k個數字來調整,使得比第k個數字小的所有數字都位於數組左邊,比第k個數字大的所有數字都位於數組右邊。這樣調整之後,位於數組中左邊的k個數字就是最小的k個數字。
void GetLeastNumbers(int* input,int n,int* output,int k)
{
if(input==NULL||output==NULL||k>n||n<=0||k<=0)
return;
int start=0;
int end=n-1;
//Partiton函數返回比較標準值的下標
int index=Partition(input,n,start,end);
while(index!=k-1)
{
if(index>k-1)
{
end=index-1;
index=Partition(input,n,start,end);
}
else
{
start=index+1;
index=Partition(input,n,start,end);
}
}
for(int i=0;i<k;++i)
output[i]=input[i];
}
另一種適合於處理海量數據的方法:基於數據容器
先創建一個大小爲k的數據容器來存儲最小的k個數字,接下來我們每次從輸入的n個整數中讀入一個數。
如果容器內已有數字少於k,則直接把這次讀入的整數放入容器;
如果容器中已有k個數字,即容器已滿,需要找出已有的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=leastNumbers.begin();
if(*iter<*(leastNumbers.begin())
{
leastNumbers.erase(iterGreatest);
leastNumbers.insert(*iter);
}
}
}
}