加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

第K小元素(时间复杂度达O(n))

(2008-07-14 09:10:13)
标签:

杂谈

分类: 编程珠玑
找第K小元素这个问题,我们第一想到的算法可能是是先预排序,再取第k个。
这个方法很简单,但是却使用大炮打蚊子,大材小用。
因为我们无需知道整个数列,只需知道部分子序列则可。
­
找第K小元素经常联系到的一个问题是找中位数问题:
如果有偶数个,则找第n/2或n/2+1个小元素则可找到中位数;
如果有奇数个,则找第n/2+1个小元素则可找到中位数。
­
以下是找第K小元素的C++代码。
利用的快速排序的思想。
但有区别:
快速排序需要处理两个子序列,而它只需要处理一个。
比较次数的递推式为:O(n)=O(n/2)+(n)
时间复杂度约为O(n).
效率果然高!
­
#include"stdio.h"
int GetMinK(int A[],int n,int k)
{
int s=-1,i=0,j=n-1,temp;
int beg=i;
int end=j;
while(s!=k)
{
  beg=i;
  end=j;
  temp=A[i];
  while(i<j)
  {
   while(i<j&&A[j]>=temp)j--;A[i]=A[j];
            while(i<j&&A[i]<=temp)i++;A[j]=A[i];
  }
  A[i]=temp;
  s=i;
 
  for(int index=0;index<10;index++)printf("%d ",A[index]); printf("\n");
  
  if(s==k)return A[k];
  if(s>k){i=beg;j--;}
  if(s<k){j=end;i++;}
}
}
void main()
{
int A[]={0,-2,3,-4,5,-6,7,80,9,-10};
int k=3;
printf("第%d小元素为:(从0开始)\n%d ",k,GetMinK(A,10,k));
}找第K小元素这个问题,我们第一想到的算法可能是是先预排序,再取第k个。
这个方法很简单,但是却使用大炮打蚊子,大材小用。
因为我们无需知道整个数列,只需知道部分子序列则可。
­
找第K小元素经常联系到的一个问题是找中位数问题:
如果有偶数个,则找第n/2或n/2+1个小元素则可找到中位数;
如果有奇数个,则找第n/2+1个小元素则可找到中位数。
­
以下是找第K小元素的C++代码。
利用的快速排序的思想。
但有区别:
快速排序需要处理两个子序列,而它只需要处理一个。
比较次数的递推式为:O(n)=O(n/2)+(n)
时间复杂度约为O(n).
效率果然高!
­
#include"stdio.h"
int GetMinK(int A[],int n,int k)
{
int s=-1,i=0,j=n-1,temp;
int beg=i;
int end=j;
while(s!=k)
{
  beg=i;
  end=j;
  temp=A[i];
  while(i<j)
  {
   while(i<j&&A[j]>=temp)j--;A[i]=A[j];
            while(i<j&&A[i]<=temp)i++;A[j]=A[i];
  }
  A[i]=temp;
  s=i;
 
  for(int index=0;index<10;index++)printf("%d ",A[index]); printf("\n");
  
  if(s==k)return A[k];
  if(s>k){i=beg;j--;}
  if(s<k){j=end;i++;}
}
}
void main()
{
int A[]={0,-2,3,-4,5,-6,7,80,9,-10};
int k=3;
printf("第%d小元素为:(从0开始)\n%d ",k,GetMinK(A,10,k));
}

0

阅读 收藏 喜欢 打印举报/Report
前一篇:归并排序
后一篇:堆排序
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有