面试最经常考察的排序应该就是 快速排序,归并排序和堆排序了。
例如题目:10万个数字中找最大的10个数。
1,因为10万个数可以放到内存中,首先可以考虑使用快排的 Partition 函数解决这个问题。
若Partition 函数得到 index 值为 99990,则从下标 99990 到下标 99999 的10个数字就是最大的 10 个数。
时间复杂度为 O(n)。
int Partition(int data[],int length,int start,int end)
{
if(data == NULL || length <=0 || start <0 || end >= length)
return;
int index = RandomInRange(start,end);
Swap(&data[index],&data[end]);
int small = start - 1;
for (index = start;index < end;++index)
{
if(data[index] < data[end])
{
++small;
if(small != index)
Swap(&data[small],&data[index]);
}
}
++small;
Swap(&data[small],&data[end]);
return small;
}
void GetMaxNumbers(int* input,int n,int* output,int k)
{
if(input == NULL || output == NULL || n <= 0||k<=0||k>n)
return;
int start = 0;
int end = n - 1;
int index = Partition(input,n,start,end);
while(index != (n-k))
{
if(index < n-k)
{
start = index + 1;
index = Partition(input,n,start,end);
}
else
{
end = index - 1;
index = Partition(input,n,start,end);
}
}
for(int i = n-k ;i < n;++i)
{
output[i] = input[i];
}
}
2 可以考虑使用堆排序的思想解决。此处考虑小根堆较为适合。
使用前10个节点建立一个小根堆,然后继续遍历其余的所有数字。因为根据小根堆的性质,最小节点为根节点。如果遍历到的数字比小根堆根节点小,则直接忽略,该遍历到的数一定不是最大的10个数之一。若遍历到的数比小根堆的根节点值大,则用该节点直接替换小根堆根节点,再调整堆即可。这样仅需维护10个节点的小根堆即可。
。。。待续