(转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/06/2624799.html)

寻找N个数中最大的K个数,本质上就是寻找最大的K个数中最小的那个,也就是第K大的数。

可以使用二分搜索的策略来寻找N个数中的第K大的数。对于一个给定的数p,可以在O(N)的时间复杂度内找出所有不小于p的数。

寻找第k大的元素:

#include <iostream>
using namespace std; //快速排序的划分函数
int partition(int a[],int l,int r)
{
int i,j,x,temp;
i = l;
j = r+1;
x = a[l];
//将>=x的元素换到左边区域
//将<=x的元素换到右边区域
while (1)
{
while(a[++i] > x);
while(a[--j] < x);
if(i >= j) break;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
a[l] = a[j];
a[j] = x;
return j;
} //随机划分函数
int random_partition(int a[],int l,int r)
{
int i = l+rand()%(r-l+1);//生产随机数
int temp = a[i];
a[i] = a[l];
a[l] = temp;
return partition(a,l,r);//调用划分函数
} //线性寻找第k大的数
int random_select(int a[],int l,int r,int k)
{
int i,j;
if (l == r) //递归结束
{
return a[l];
}
i = random_partition(a,l,r);//划分
j = i-l+1;
if(k == j) //递归结束,找到第K大的数
return a[i];
if(k < j)
{
return random_select(a,l,i-1,k);//递归调用,在前面部分查找第K大的数
}
else
return random_select(a,i+1,r,k-j);//递归调用,在后面部分查找第K大的数
} int main()
{
int a[]={1,2,3,4,6,6,7,8,10,10}; cout<<random_select(a,0,9,1)<<endl;
cout<<random_select(a,0,9,5)<<endl;
return 0;
}

如果所有N个数都是正整数,且它们的取值范围不太大,可以考虑申请空间,记录每个整数出现的次数,然后再从大到小取最大的K个。比如,所有整数都在(0, MAXN)区间中的话,利用一个数组count[MAXN]来记录每个整数出现的个数(count[i]表示整数i在所有整数中出现的个数)。只需要扫描一遍就可以得到count数组。然后,寻找第K大的元素:

for(sumCount = 0, v = MAXN-1; v >= 0; v--)
{
sumCount += count[v];
if(sumCount >= K)
break;
}
return v;

极端情况下,如果N个整数各不相同,我们甚至只需要一个bit来存储这个整数是否存在(bit位为1或为0),这样使用的空间可以大大压缩。

当然也可以使用像计数排序、桶排序等这些以O(N)的时间排序算法也可以寻找第K大的数,但这也是以空间换时间为代价的。

实际情况下,并不一定保证所有元素都是正整数,且取值范围不太大。上面的方法仍然可以推广使用。如果N个数中最大的数Vmax,最小的Vmin,我们可以把这个区间[Vmax,Vmin]分成M块,每个小区间的跨度为d=(Vmax-Vmin)/M,即[Vmin,Vmin+d],[Vmin+d,Vmin+2d]......然后,扫描一遍所有元素,统计各个小区间中的元素个数,就可以知道第K大的元素在哪一个小区间。然后,再在那个小区间中找第K大的数(此时这个小区间中,第K大的数可能就是第T大的数了,这个T和每个小区间的个数有关)。我们需要找一个尽量大的M,但M的取值受到内存的限制。

O(N)的时间寻找最大的K个数的更多相关文章

  1. 算法系列:寻找最大的 K 个数

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  2. 第2章 数字之魅——寻找最大的K个数

    寻找最大的K个数 问题描述 在面试中,有下面的问答: 问:有很多个无序的数,我们姑且假定它们各不相等,怎么选出其中最大的若干个数呢? 答:可以这样写:int array[100] …… 问:好,如果有 ...

  3. 03寻找最小的k个数

    题目描述:查找最小的k个元素         题目:输入n个整数,输出其中最小的k个.         例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 1:最简单 ...

  4. 算法练习:寻找最小的k个数

    参考July的文章:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数题目描述:查找最小的k个元素题目:输入n个整数,输出其中 ...

  5. 编程之美2.5:寻找最大的K个数

    编程之美2.5:寻找最大的K个数 引申:寻找第k大的数: 方法一: // 选择第k大的数(通过改进快速排序来实现) public static void SelectShort(int[] array ...

  6. 寻找最大的k个数问题

    这是编程之美书第2.5节的一道题目. 各种解法: 解法一,用nlgn复杂度的排序算法对数组进行从大到小排序,取前K个.但这方法做了两件不必要做的事:它对想得到的K个数进行了排序,对不想得到的n-K个数 ...

  7. 【编程之美】2.5 寻找最大的k个数

    有若干个互不相等的无序的数,怎么选出其中最大的k个数. 我自己的方案:因为学过找第k大数的O(N)算法,所以第一反应就是找第K大的数.然后把所有大于等于第k大的数取出来. 写这个知道算法的代码都花了2 ...

  8. 寻找最大的K个数(下)

    接着昨天的写,里面的代码包含昨天的 #include <iostream> using namespace std; #define N 50 //初始化数组 , , , , , , , ...

  9. 算法笔记_035:寻找最小的k个数(Java)

    目录 1 问题描述 2 解决方案 2.1 全部排序法 2.2 部分排序法 2.3 用堆代替数组法 2.4线性选择算法   1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 ...

随机推荐

  1. 中文数据解码报错 UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence

    UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence 失败原因: ...

  2. cmake构建时指定编译器架构(x86 or x64)

    vs2015 x64编译器为例,cmake命令如下: cmake -G "Visual Studio 14 Win64" path\to\source\dir 去掉Win64,就是 ...

  3. MySql 5.7 新特性概览

    安全的提升 1.1 在Mysql 8版本中,caching_sha2_password 是一个缺省的认证插见.5.7 版本的客户端支持 caching_sha2_password 的客户端认证. 1. ...

  4. python nose测试框架全面介绍十---用例的跳过

    又来写nose了,这次主要介绍nose中的用例跳过应用,之前也有介绍,见python nose测试框架全面介绍四,但介绍的不详细.下面详细解析下 nose自带的SkipTest 先看看nose自带的S ...

  5. day_10py 简单地名字管理系统

    #!/usr/bin/env/python #-*-coding:utf-8-*- ''' 名字管理系统 做程序迭代,由点到面一点一点来 ''' # 1.打印功能提示 print("=&qu ...

  6. 具有键“XXX”的 ViewData 项属于类型“System.Int32”,但它必须属于类型“IEnumerable<SelectListItem>

    原因是Edit视图中有@Html.DropDownListFor(m => m.BirthdayAD... 但是没有从Controller中没有设置值

  7. js 去除金额的千位分隔符

    export function delcommafy(num) { if (num != undefined) { num = num.toString(); num = num.replace(/[ ...

  8. [No0000132]正确使用密码加盐散列[译]

    如果你是一个 web 开发工程师,可能你已经建立了一个用户账户系统.一个用户账户系统最重要的部分是如何保护密码.用户账户数据库经常被黑,如果你的网站曾经被攻击过,你绝对必须做点什么来保护你的用户的密码 ...

  9. tensorflow 的tf.split函数的用法

    将张量进行切分 tf.split( value, num_or_size_splits, axis=0, num=None, name='split' ) value: 待切分的张量 num_or_s ...

  10. 从一个点的长度是多少说起(Talking started from the length of a point on the real number line)

    From the perspective of analytical geometry, an interval is composed of infinitely many points, whil ...