对于一个非有序的数组A[p..r],求数组中第k小的元素。

如何考虑

排序(部分排序)就不用说了。。o(nlgn),当然如果在实际情况中要一直取值,当然要排序后,一次搞定,以后都是O(1)

我们这里提供了取一次最K小的一个o(n)的解法,
用了快速排序的一种思想,
关键在于划分只一个部分,我们知道快速排序选择一个pivot对数组进行划分,左边小于pivot,右边大于等于pivot,
所以我们计算左边小于pivot(加上pivot)的个数count总共有多少,如果等于k,正是我们所要的,如果大于k,说明第k小的
数在左边,那就在左边进行我们的递归;否则,在右边,那么说明右边的第k-count小的数就是我们所要的,在右边进行
我们的递归。

3.代码
当k>(r-p+1),返回最大值,当k<1,返回最小值

#include<iostream>
using namespace std;
#include<time.h> inline void Swap(int a[],int i,int j)
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
} int Partition(int a[],int p,int r)//根据pivot a[r]来划分数组
{
int pivot=a[r];
int low=p-;
int i;
for(i=p;i<r;i++)
{
if(a[i]<=pivot)
Swap(a,++low,i);
}
Swap(a,++low,r);
return low;
} int RondomPartition(int a[],int p,int r)
{
int i=p+rand()%(r-p+);//随机选择一个pivot来划分
Swap(a,i,r);
return Partition(a,p,r);
} int SelectKMin(int a[],int p,int r,int k)
{
if(p==r)
return a[p];
int q=RondomPartition(a,p,r);
int count=q-p+;//计算 a[p..q]的元素数量
if(k==count)//刚好,返回
return a[q];
else if(k<count)//在前半部分
return SelectKMin(a,p,q-,k);
else //在后半部分
return SelectKMin(a,q+,r,k-count);
} const int N=;
const int K=;
int a[N]; int main()
{
int i;
for(i=;i<N;i++)
a[i]=i;
srand(unsigned(time(NULL)));
for(i=;i<K;i++){//获得0-100不重复随机数
Swap(a,i,i+rand()%(N-i));
}
int k;
while(cin>>k)
{
cout<<SelectKMin(a,,K-,k)<<endl;
}
return ;
}
本文实例讲述了C++实现查找中位数的O(N)算法和Kmin算法,分享给大家供大家参考。具体方法如下:
利用快速排序的partition操作来完成O(N)时间内的中位数的查找算法如下:
? #include <iostream>
#include <cassert>
#include <algorithm>
#include <iterator> using namespace std; int array[] = {, , , , , , };
const int size = sizeof array / sizeof *array; int partition(int *array, int left, int right)
{
if (array == NULL)
return -; int pos = right;
right--;
while (left <= right)
{
while (left < pos && array[left] <= array[pos])
left++; while (right >= && array[right] > array[pos])
right--; if (left >= right)
break; swap(array[left], array[right]);
}
swap(array[left], array[pos]); return left;
} int getMidIndex(int *array, int size)
{
if (array == NULL || size <= )
return -; int left = ;
int right = size - ;
int midPos = right >> ;
int index = -; while (index != midPos)
{
index = partition(array, left, right); if (index < midPos)
{
left = index + ;
}
else if (index > midPos)
{
right = index - ;
}
else
{
break;
}
} assert(index == midPos);
return array[index];
} void main()
{
int value = getMidIndex(array, size); cout << "value: " << value << endl;
}
寻找kmin算法如下: int findKMin(int *array, int size, int k)
{
if (array == NULL || size <= )
return -; int left = ;
int right = size - ;
int index = -; while (index != k)
{
index = partition(array, left, right); if (index < k)
{
left = index + ;
}
else if (index > k)
{
right = index - ;
}
else
{
break;
}
} assert(index == k);
return array[index];
}
希望本文所述

利用最小堆

此种方法为常用方法,建立一个大小为K的最小堆。每次遍历数组时,需要判断是否需要加入堆中。
   堆中存储着的是最大的k个数字,但是若是需要插入堆中,则需要对堆进行调整时间为o(log k)。
   全部的时间复杂度为o(n * log k)。
   
  这种方法当数据量比较大的时候,比较方便。因为对所有的数据只会遍历一次,第一种方法则会多次遍历
  数组。 如果所查找的k的数量比较大。可以考虑先求出k` ,然后再求出看k`+1 到 2 * k`之间的数字,然后
  一次求取。

#include<iostream>
using namespace std; void minHeapify(int a[],int heapSize,int i)
{
int l=*i+;
int r=*i+;
int smallest;
if(l<heapSize && a[l]<a[i])
smallest=l;
else
smallest=i;
if(r<heapSize && a[r]<a[smallest])
smallest=r; if(smallest!=i)
{
swap(a[i],a[smallest]);
minHeapify(a,heapSize,smallest);
}
} void bulidMinHeap(int a[],int n)
{
int heapsize=n;
for(int i=n/-;i>=;i--)
minHeapify(a,heapsize,i); }
#define aSize 10; int main()
{
int a[]={,,,,, ,,,,};
int n=sizeof(a)/sizeof(a[]);
int k=;
bulidMinHeap(a,k);
//如果X比堆顶元素Y小,则不需要改变原来的堆
//如果X比堆顶元素Y大,那么用X替换堆顶元素Y,在替换之后,X可能破坏了最小堆的结构,需要调整堆来维持堆的性质
for(int i=n-;i>=k;i--)//>=k,因为第0个也存
{
if(a[]<a[i])
{
swap(a[],a[i]);
minHeapify(a,k,);
}
}
for(int i=;i<k;i++)
cout<<a[i]<<endl; }

上面的输出:10,16,14,可以看到第k大的存在a[0],为10.

http://blog.csdn.net/sjf0115/article/details/8603441

http://blog.csdn.net/rein07/article/details/6742933

top k 算法的更多相关文章

  1. 程序员编程艺术:第三章续、Top K算法问题的实现

    程序员编程艺术:第三章续.Top K算法问题的实现 作者:July,zhouzhenren,yansha.     致谢:微软100题实现组,狂想曲创作组.     时间:2011年05月08日    ...

  2. Top K算法

    应用场景: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.        假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果 ...

  3. hihoCoder 1133 二分·二分查找之k小数(TOP K算法)

    #1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很 ...

  4. 使用堆实现Top K 算法 JS 实现

    1. 堆算法Top,时间复杂度 O(LogN) function top(arr,comp){ if(arr.length == 0){return ;} var i = arr.length / 2 ...

  5. Top K 算法详解

    http://xingyunbaijunwei.blog.163.com/blog/static/7653806720111149318357/ 问题描述         百度面试题:        ...

  6. 百度面试题——top K算法

    需求 从一亿个数据中,找出其中最小的10个数. 分析 最笨的方法就是将这一亿个数据,按从小到大进行排序,然后取前10个.这样的话,即使使用时间复杂度为nlogn的快排或堆排,由于元素会频繁的移动,效率 ...

  7. 百度面试题——top K算法

    需求 从一亿个数据中,找出其中最小的10个数. 分析 最笨的方法就是将这一亿个数据,按从小到大进行排序,然后取前10个.这样的话,即使使用时间复杂度为nlogn的快排或堆排,由于元素会频繁的移动,效率 ...

  8. Top K问题-BFPRT算法、Parition算法

    BFPRT算法原理 在BFPTR算法中,仅仅是改变了快速排序Partion中的pivot值的选取,在快速排序中,我们始终选择第一个元素或者最后一个元素作为pivot,而在BFPTR算法中,每次选择五分 ...

  9. 优先队列PriorityQueue实现 大小根堆 解决top k 问题

    转载:https://www.cnblogs.com/lifegoesonitself/p/3391741.html PriorityQueue是从JDK1.5开始提供的新的数据结构接口,它是一种基于 ...

随机推荐

  1. Struts2 请求处理步骤

    1) 客户端初始化一个指向Servlet容器(例如Tomcat)的请求   2 )这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器 ...

  2. Java Web 中 过滤器与拦截器的区别

    过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法u ...

  3. linux scp ssh命令不用输入密码

    把你的本地主机用户的ssh公匙文件复制到远程主机用户的~/.ssh/authorized_keys文件中 假设本地主机linux100,远程主机linux200 一,在linux100主机里的用户 运 ...

  4. 杭电oj1236 排名

    Tips:此题比较简单,最好将每一个学生的信息构建一个结构体,另外需要注意的是,若分数相同,排序按姓名排序,我看网上很多都是使用<algorithm>中的sort算法,只需重写cmp函数即 ...

  5. 能上QQ无法打开网页

    能上QQ无法上网电脑故障解决方法 Winsock协议配置故障解决方法 第1步 :单击开始菜单中的运行,并在打开的运行窗口中键入“cmd”并回车确定,打死命令提示符窗口. 第2步 :在打开的命令提示符窗 ...

  6. 解决jQuery.live在mobile safari(iphone / ipad / ipod)绑定失败的问题

    解决方案: 给要使用live绑定事件的元素,添加“cursor:pointer”样式即可! 如: a,input,td{cursor:pointer;}

  7. ORACLE AWR概述及生成AWR报告

    1.Overview of the Automatic Workload Repository The Automatic Workload Repository (AWR) collects, pr ...

  8. T-SQL事务

    事务 订火车票的时候,下一个订单,这个订单中,包含多个购买信息,要么全部执行,要么全部不执行,合作事务就是来处理这种模型的一种机制. --关键字:transaction 或 tran 简写形式 --开 ...

  9. SVG-1

    <rect>矩形 <circle>圆 <ellipse>椭圆 <line>直线 <polyline>折线 <polygon>标签 ...

  10. 阿里大鱼短信接口整合Tp3.2.3开发整理

    阿里大鱼 http://www.alidayu.com/ 的短信接口总体是不错的,别安驹个人认为不管是从性价比还是稳定性上都是跟同类的短信接口好些,毕竟是大公司的东西不会差到哪去.下面把之前开发的短信 ...