对于一个非有序的数组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. ORACLE CHECK CONSTRAINT使用示例(转载) .

    看下面的例子: CREATE TABLE temp (age NUMBER(3)); ALTER TABLE temp ADD CONSTRAINT ck_temp_age CHECK     ((A ...

  2. jquery中attr()与prop()函数用法实例详解(附用法区别)

    本文实例讲述了jQuery中attr()与prop()函数用法.分享给大家供大家参考,具体如下: 一.jQuery的attr()方法 jquery中用attr()方法来获取和设置元素属性,attr是a ...

  3. dict.get('key')和dict['key']的区别

    dict['key']只能获取存在的值,如果不存在会触发KeyError dict.get('key', default=None)如果不存在,返回一个默认值

  4. Android Studio 如何导入第三方jar 包

    第一步: 将第三方jar包加入到libs文件夹中 第二步: 分为两种情况 第一种是打开工程所在Project Structure,然后选择Dependencies,点击那个加号选择File Depen ...

  5. JIT和程序的首次执行

    由于C#源代码经过编译器编译生成的是IL代码,而IL是与CPU无关的机器语言.因此当程序运行于特定的CPU时,首先必须将IL转换成本地CPU指令,这正是JIT(Just-In-Time)编译器的任务. ...

  6. 关于web的流程

    1.先确定好样式,布局,风格 2.之后的页面只是加一些HTML标签而已.

  7. Blacksmith test

    最近使用Blacksmith 对各种K,V数据库做了一些测试,从中了解了一些各种数据库的设计方式,比较各种数据库的性能 BlaskSmith是我们自己的产品,详细的产品信息可以在github上看到 h ...

  8. javac: cannot execute binary file

    # java/jdk1.6.0_12/bin/javac-bash: java/jdk1.6.0_12/bin/javac: cannot execute binary file   后来检验,检查了 ...

  9. SQL Server 2008数据库的一些基本概念 区、页、行

    原文地址:http://www.cnblogs.com/liuzhendong/archive/2011/10/11/2207361.html 以前总是没弄明白这些基本概念,现在整理如下: 1.区: ...

  10. Objective-C 基本语法:实例变量与成员变量的区别.l........实例方法和类方法区别

    http://leopard168.blog.163.com/blog/static/16847184420138153296930/ http://blog.csdn.net/thdxs/artic ...