(转: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. windows系统下,express构建的node项目中,如何用debug控制调试日志

    debug是一款控制日志输出的库,可以在开发调试环境下打开日志输出,生产环境下关闭日志输出.这样比console.log方便多了,console.log只有注释掉才能不输出. debug库还可以根据d ...

  2. nginx-启动|关闭|重新加载配置文件的命令

    1.1 进入操作目录 D: cd D:\NginxTest\nginx-1.10.2 1.2 启动指令 nginx -c conf\nginx.conf 1.3 关闭指令 nginx -s stop ...

  3. linux相关(3)

    1. shell环境变量 能够存在于本shell进程及其子shell进程的变量.变量可以从父shell进程传递给子shell进程,而不能反过来,因此环境变量在子shell进程中无论如何修改都不会影响到 ...

  4. Unity3D Shader 马赛克后期效果

    //效果图 //Shader代码 Shader "Hidden/Mosaic" { Properties { _MainTex ("Texture", 2D) ...

  5. 【CF582E】Boolean Function 树形DP+FWT

    [CF582E]Boolean Function 题意:给你一个长度为n的表达式,其中未知数有A,B,C,D和?,运算有&和|和?(表达式中用括号确定了唯一的运算顺序).?代表A,B,C,D或 ...

  6. jdbc --- javabean

    第一部分: javaBean 类  要和数据库表的字段一一对应 package com.ljs.bean; public class UserBean { private int id; privat ...

  7. 【魔改】莫队算法+组合数公式 杭电多校赛4 Problem B. Harvest of Apples

    http://acm.hdu.edu.cn/showproblem.php?pid=6333 莫队算法是一个离线区间分块瞎搞算法,只要满足:1.离线  2.可以O(1)从区间(L,R)更新到(L±1, ...

  8. shell之awk面试小案例

    [root@chavinking mnt]# cat textfile chavinking 1 2 3 4 5 6 nope 1 2 3 4 5 6 [root@chavinking mnt]# c ...

  9. [daily][cgroup] 使用cgroup限制进程的CPU占用

    参考: https://segmentfault.com/a/1190000008323952 1. 找到cgroup设置的地方. [root@D128 ~]# mount -l |grep cpu ...

  10. [daily][mariadb][mysql] mariadb快速设置

    参考: https://wiki.archlinux.org/index.php/MySQL 1. 安装 使用pacman常规安装 2. btrfs 禁用CoW mariadb的数据文件如果存储在bt ...