对于一个非有序的数组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. coco2d-x中的坐标系问题

    (1)OpenGL坐标系 Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然支持OpenGL坐标系.该坐标系原点在屏幕左下角,x轴向右,y轴向上. (2)屏幕坐标系 屏幕坐标系使用的 ...

  2. python学习day8

    目录 一.异常 二.多线程 三.守护线程与join 四.GIL与多线程锁 五.递归锁与信号量 六.线程间同步与交互 七.多进程 八.进程间通信与数据共享 九.进程池 一.异常 1.异常处理 在编程过程 ...

  3. COB(Chip On Board)的製程簡單介紹

    前面提及 COB 的生產與 IC 的封裝製程幾乎是一致的,除了把 leadframe 改成了 PCB,把封膠由 molding 改成 dispensing,少了 triming & marki ...

  4. perl 调用按钮输出到文本框

    sub push_b4 { #$txt -> insert('end'); #select $txt; system("expect c:\\\\expect.txt >expe ...

  5. Photoshop技能167个经典的Photoshop技巧大全

    Photoshop技能167个经典的Photoshop技巧大全 学PS基础:Photoshop 技能167个­ 经典的Photoshop技巧大全,如果你是初级阶段的水平,熟读此文并掌握,马上进阶为中级 ...

  6. Android的读写文件权限

    设置文件生成的权限: public static boolean saveInfo( Context context, String userName, String userPass, int mo ...

  7. 面向对象继承实例(a如何继承b)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. NYOJ 46-最少乘法次数(数论)

    题目地址:pid=46">NYOJ 46 思路:能够化成二进制来求解.结果是最高位的位数-1+最高位后面1的个数.比如:对于3.它的二进制代码为11,就是用这个最高位(2-1)加上后面 ...

  9. Linux下多核环境Erlang的SMP測试

    目标 (1)       了解在多核cpu环境下,erlang并发进程调度对各个cpu核负载的影响: (2)       Erlang虚拟机的内存添加机理: (3)       Erlang进程的调度 ...

  10. 【机房系统知识小结点系列】之遍历窗体中的控件,判断Text是否为空?

    做机房系统时,几乎每个窗体中都会用到判断界面中的控件是否为空的情景.我们曾经是这样走来的: 第一版: 好处:对窗体界面中的Text等控件,逐一做判断,当用户输入某一项为空的时候,会议弹出框的形式,告诉 ...