电话面试----关于前k个最小数的问题

来源:互联网 发布:linux mount usb 编辑:程序博客网 时间:2024/04/28 07:15

前几天,接到电话面试,结果问了一个算法题,说给一些乱序的整数,找出前k个最小整数,当时直接想到的就是先用nlogn的算法比如快速排序进行升序排列,然后取前k个值就行了,但是对方说还有没有更加高效的方法。想了半天没有想起来。挂完电话后我想到虽然使用快速排序可以达到目的,但是却把所有的序列都进行了排序,做了很多无用功。为了去除前k个最小值,我们可以在快速排序的基础上进行剪枝优化,去除一些不必要的排序。模仿快排算法,虽然快排使用分而治之的思想提高了排序效率,但是目标要求的是查找前k个最小值,再这样的背景下,分治却成为了影响性能的因素。因为我们在进行一次划分操作后,中轴的位置(在这里是第几个的意思)如果大于k值的话,中轴后面连同中轴本身都不是此问题的解集的一部分。如果等于k的话查找结束,连同中轴本身就是问题解。如果小于k的话,就可以忽略中轴以后的数据了,没必要在对其进行分解排序了,因为他们肯定不是问题的解。


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void search_seventh(int *a,int n,int k)
{


if(n<=k||n<=0||k<=0)
{
return ;
}
else
{
int d=0;
for(d=0;d<n;d++)
{
printf("%d ",a[d]);
}
printf("\n");


int i=0,j=n-1;
int temp=*a;
while(i<j)
{
while(temp<*(a+j)&&i<j)j--;
*(a+i)=*(a+j);
while(temp>=*(a+i)&&i<j)i++;
*(a+j)=*(a+i);
}
*(a+i)=temp;
if(i+1==k)
  return ;
else if(i+1<k)
{
search_seventh(a+i+1,n-i-1,k-i-1);//重新制定搜索集,以及此搜索集的需要搜索出的最小值个数,在i+1<k情况下

//搜索集减去此次搜到的解个数,重新定义搜索集,搜索集开始处为中轴下一个,搜索个数同理
}
else
{
search_seventh(a,i,k);//重新定制搜索集,因为i+1>k,所以前面的所有数据不包括中轴作为搜索集。搜索个数为k个。
}


}
}
int main()
{
int a[20]={6,7,2,3,5,6,89,4,34,11,1,4,45,31,5,4,4,4,4,4};
int k=0,i=0;
while(1)
{
scanf("%d",&k);
search_seventh(a,20,k);
for(i=0;i<k;i++)
{
printf("%d ",a[i]);
}


printf("\n");
}
  return 0;

其实这个题还可以进行优化,题目是要求最小k个,所以可以设置一个容量为k的最小堆,取数组里前k个数,调整为最小堆,然后对原始数组里k后的元素,进行一次遍历,将元素插入到堆中,这样时间复杂度就降到了O(logk*n),如果k是个可以当做常数的变量,则算法复杂度为O(n)

0 0
原创粉丝点击