对于一个非有序的数组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. linux 安装nodejs

    首先去官网下载代码,这里一定要注意安装分两种,一种是Source Code源码,一种是编译后的文件. 我就是按照网上源码的安装方式去操作编译后的文件,结果坑了好久好久.     注意看好你下载的是什么 ...

  2. python文件处理及装饰器

    1.文件处理: Python处理文件的流程比较简单,大致分为以下几个: 打开文件==>处理文件==>生成新文件==>写入文件 先说怎么打开一个文件: 打开一个文件可以有多种写法,下面 ...

  3. 喷水装置(一)--nyoj题目6

    喷水装置(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中 ...

  4. ASP.NET MVC5+ORACLE 身份认证

    菜鸟来的,刚接触mvc,看到mvc5上默认带有identity身份验证的东西,公司用的oracle数据库,便想着东西能不能支持oracle数据库,折腾了半天弄出下面的东西来,有些东西可能不太准确,望大 ...

  5. 如何设置 Internal 类,方法,属性对其他项目可见

    internal 修饰符时程序集内部其他类可见.但对程序集外的类不可见,这样就很好的封装了可见性. 但是,我们也许会碰到类似的情况,特别是基于已有代码开发新的代码时,你会发现很多 internal 的 ...

  6. C++异常处理的编程方法(阿愚,整整29集)

    相遇篇 <第1集 初次与异常处理编程相邂逅> <第2集 C++中异常处理的游戏规则> <第3集 C++中catch(…)如何使用> <第4集 C++的异常处理 ...

  7. how to remove MouseListener / ActionListener on a JTextField

    I have the following code adding an ActionListener to a JTextField: chatInput.addMouseListener(new j ...

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

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

  9. ios 开发指南

    苹果Xcode帮助文档阅读指南 iOS开发官方文档汇总 翻译"iPhone SDK 开发"之UIKit使用… iOS中arc的设置与使用

  10. Embedded software develop step

    x86 –>embeded so you you  must familiar with x86 first-