标签:算法 快速排序 二分查找
解法一:
解法二:
利用快速排序的思想,假设N个数存储在数组S中,我们从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb,Sa中的元素大于等于X,Sb中的元素小于X。
伪代码如下:
Kbig(S,k)
if(k<=0) return []
if (length S<=k):
return S
(Sa,Sb)=Partition(S)
return Kbig(Sa,k).Append(Kbig(Sb,k-length Sa))
Partition(S):
Sa=[]
Sb=[]
//随机选择一个数作为分组标准,以避免特殊数据下的算法退化
//也可以通过对整个数组进行洗牌预处理实现这个目的
//Swap(S[1],S[Random()%length S])
p=S[1]
for i in[2,length S]:
S[i]>p?Sa.Append(S[i]):Sb.Append(S[i])
//将p加入较小的组,可以避免分组失败,是分组更均匀,提高效率
length Sa<length Sb? Sa.Append(p):Sb.Append(p)
return (Sa,Sb)
解法三:
采用二分查找的方法,寻找N个数中最大的K个数,本质上就是寻找最大的K个数中最小的那个,也就是第K大的数。假如N个数中最大的数为Vmax,最小的数为Vmin;那么这N个数中的第K大数一定在区间[Vmin,Vmax]之间。那么,可以在这个区间内二分搜索N个数中的第K大数p.
伪代码如下:
while (Vmax-Vmin>delta)
{
Vmid=Vmin+(Vmax-Vmin)*0.5;
if (f(arr,N,Vmid)>=K)
{
Vmin=Vmid;
}
else
Vmax=Vmid;
}
伪代码中f(arr,N,Vmid)返回数组arr[0,....,N-1]中大于等于Vmid的数的个数.delta的取值要比所有N个数中的任意两个不相等的元素差值之最小值小。
解法四:
适用于数据个数N很大的情况,100亿?
图2-1是一个堆,用一个数组h[]表示。每个元素h[i],它的父亲节点是h[i/2],儿子是h[2*i+1]和h[2*i+2].没新考虑一个数X,需要进行的更新操作伪代码如下:
if (X>h[0])
{
h[0]=X;
p=0;
while (p<K)
{
q=2*p+1;
if (q>=K)
break;
if((q<K-1)&&h[q+1]<h[q])
q=q+1;
if (h[q]<h[p])
{
t=h[p];
h[p]=h[q];
h[q]=t;
}
else
break;
}
}
时间复杂度为O(N*log2K).
解法五:
确定的线性算法。可以通过改进计数排序,基数排序等来得到一个更高效的算法。但是算法的适用范围受到一定的限制。
for(sumCount=0,v=MAX-1;v>=0;v--)
{
sumCount+=count[v];
if (sumCount>=k)
break;
}
return v;
寻找最大的K个数
标签:算法 快速排序 二分查找
原文地址:http://blog.csdn.net/wangfengfan1/article/details/45132351