微软算法面试(5):查找最小的k个元素(数组)
题目:输入n个整数,输出其中最小的k个。
例如输入7,2,4,5,1,3,6,8这8个数字,则最小的4个数字为1,2,3和4。
下面使用快速排序和分治法的思想,
1)先找选一个元素a遍历一次剩余的其他元素,使得a左边的元素都是小于它的,a右边的元素都是大于它的。
2)再统计a 左边的元素或者包括a 与 k的关系,等于的话,就直接输出,大于,那就在左边里面继续1),小于的话,那就在右边里面继续查找k-左边元素的个数-1个最小的整数。
#include <iostream>
#include<vector>
using namespace std;
//使用快速排序的思想,查找最小的k个数
void findmink(int* data, int i, int j, int k, vector<int>& res)
{
//使用一次快速排序步骤
int ii = i+1;
int jj = j-1;
int pos = i;
while(ii <= jj)
{
while(ii <= jj && data[jj] > data[pos])
jj --;
if(ii <= jj)
{
int tmp = data[pos];
data[pos] = data[jj];
data[jj] = tmp;
pos = jj;
jj --;
}
while(ii <= jj && data[ii] < data[pos])
ii ++;
if(ii <= jj)
{
int tmp = data[pos];
data[pos] = data[ii];
data[ii] = tmp;
pos = ii;
ii --;
}
}
if(pos-i+1 == k)
{//OK
for(ii=i; ii <= pos; ii++)
res.push_back(data[ii]);
}
else if(pos-i == k)
{
for(ii=i; ii < pos; ii++)
res.push_back(data[ii]);
}
else if( pos-i+1 < k)
{
for(ii=i; ii <= pos; ii++)
res.push_back(data[ii]);
findmink(data, pos +1 , j, k-pos +i -1, res);
}
else
{
findmink(data, i, pos, k, res);
}
}
int main()
{
int array[8] = {7,2,4,5,1,3,6,8};
vector<int> mink;
findmink(array, 0, 8, 4, mink);
int i = 0;
while(i<mink.size())
{
cout << mink[i++] << ",";
}
return 0;
}
输出结果为:
1,2,3,4