问题:  查找出一给定数组中第k大的数。例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8……

思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]。

2. 只需找到第k大的数,不必把所有的数排好序。我们借助快速排序中partition过程,一般情况下,在把所有数都排好序前,就可以找到第k大的数。我们依据的逻辑是,经过一次partition后,数组被pivot分成左右两部分:S左、S右。当S左的元素个数|S左|等于k-1时,pivot即是所找的数;当|S左|小于k-1,所找的数位于S右中;当|S左|>k-1,所找的数位于S左中。显然,后两种情况都会使搜索空间缩小。

算法的时间复杂度为:O(N)--详情参考算法导论。

#include<iostream>using namespace std;int Partition(int a[], int i, int j){      int  tmp = a[j];      int index =i;      if (i < j)      {            for (int k=i;k<j;k++){                  if(a[k] >= tmp){                        swap(a[index++],a[k]);                  }            }            swap(a[index],a[j]);            return index;      }}int Search(int a[], int i, int j, int k){        int m = Partition(a, i, j);        if (k==m-i+1)  return a[m];        else if (k<m-i+1)        {              return Search(a, i, m-1,k );        }    //后半段        else        {              return Search(a, m+1, j, k-(m-i+1));        }}int main(){        int a[7] = { 8,7,6,1,2,3,4 };        int k = 3;        cout << Search(a,2, 6, k);}

  上述问题对应于寻找前K大个数。上述方法对应的数据量比较小,如果N很大,100亿?甚至更多,这个时候数据不能够全部放入内存,所以要求尽可能少遍历数据。不妨设N>K,考虑前K个数中的最大K个数的一个退化的情况:所有K个数就是最大的K个数。如果考虑第K+1个数X呢?如果X比最大的K个数中的最小的数Y小,则最大的K个数保持不变。如果X比最大的K个数中个最小的数Y大,则最大的K个数要除去Y,加入X。如果用一个数组来保存前K大的数,每加入一个数X,就扫描一遍数组。得到数组中最小的数Y,用X代替Y或者保持不变。这种方法消耗的时间O(N*K)

  进一步,可以用容量为K的最小堆来存储最大的K个数。最小堆的堆顶元素就是K个数中最小的一个。每次考虑一个数X,如果X比堆顶元素Y小,则保持最小堆不变,因为这个元素比最大的K个数小。如果X

比堆顶元素Y大,那么用X替换原来的堆顶元素Y,X可能破坏原来的最小堆结构(每个结点比它的父节点大),需要更新堆来维持堆的性质。更新堆时间复杂度为O(log2K).总的算法复杂度为O(N*log2k)

 1 #include <iostream>
2 using namespace std;
3 //调整堆
4 void HeapAdjust(int a[],int i,int size)
5 {
6 int left = 2 * i + 1;
7 int right = 2 * i + 2;
8 int min = i;
9 if (left < size&&a[left] < a[min])
10 min = left;
11 if (right < size&&a[right] < a[min])
12 min = right;
13 if (min != i)
14 {
15 int temp = a[min];
16 a[min] = a[i];
17 a[i] = temp;
18 HeapAdjust(a,min,size); //避免调整之后以min为父节点的子树不是堆
19 }
20 }
21 //建立堆
22 void HeapBuild(int a[],int size)
23 {
24 for (int i = size / 2 - 1; i >= 0; i--)
25 HeapAdjust(a,i,size);
26 }
27 //k为需要查找的最大元素个数,size为数组大小,kMax存储k个元素的最小堆
28 void FindMax(int Array[], int k, int size, int kMax[])
29 {
30 for (int i = 0; i < k; i++)
31 kMax[i] = Array[i];
32 HeapBuild(kMax,k);
33 for (int j = k; j < size; j++)
34 {
35 if (Array[j] <= kMax[0]) continue;
36 kMax[0] = Array[j];
37 HeapAdjust(kMax,0,k);
38 }
39 }
40 int main()
41 {
42 int a[] = {10,23,17,8,52,35,7,1,28};
43 int k = 4;
44 int KMax[4] = {0};
45 FindMax(a,k,9,KMax);
46 for (int i = 0; i < k; i++)
47 cout << KMax[i] << endl;
48 }

查找数组中第k大的数的更多相关文章

  1. [经典算法题]寻找数组中第K大的数的方法总结

    [经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26   字体:[大 中 小] 打印复制链接我要评论   今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...

  2. 寻找数组中第K大的数

    给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...

  3. 查找无序数组中第K大的数

    思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> # ...

  4. 无序数组中第K大的数

    1. 排序法 时间复杂度 O(nlogn) 2. 使用一个大小为K的数组arr保存前K个最大的元素 遍历原数组,遇到大于arr最小值的元素时候,使用插入排序方法,插入这个元素 时间复杂度,遍历是 O( ...

  5. 4. Median of Two Sorted Arrays *HARD* -- 查找两个排序数组的中位数(寻找两个排序数组中第k大的数)

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  6. 求数列中第K大的数

    原创 利用到快速排序的思想,快速排序思想:https://www.cnblogs.com/chiweiming/p/9188984.html array代表存放数列的数组,K代表第K大的数,mid代表 ...

  7. 无序数组中第Kth大的数

    题目:找出无序数组中第Kth大的数,如{63,45,33,21},第2大的数45. 输入: 第一行输入无序数组,第二行输入K值. 该是内推滴滴打车时(2017.8.26)的第二题,也是<剑指of ...

  8. 前端算法题:找出数组中第k大的数字出现多少次

    题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...

  9. 无序数组求第K大的数

    问题描述 无序数组求第K大的数,其中K从1开始算. 例如:[0,3,1,8,5,2]这个数组,第2大的数是5 OJ可参考:LeetCode_0215_KthLargestElementInAnArra ...

随机推荐

  1. java-类和数组

    java内存划分 Java的内存划分为5个部分: 1.栈 (Stack) : 存放的都是方法中的局部变量,方法的运行一定要在栈当中 局部变量: 方法的参数,或者是方法()内部的变量 作用域: 一旦超出 ...

  2. 视频和音频的 DOM

    视频和音频的 DOM HTML5 DOM 为 <audio> 和 <video> 元素提供了方法.属性和事件. HTML5 Audio/Video 方法 方法 描述 addTe ...

  3. Html+Ajax+Webservice 实现文件跨域上传

    1. 界面HTML <p >上传文件: <input id="zfiles" type="file" name="file" ...

  4. Nacos快速入门

    什么是 Nacos Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供 ...

  5. 初学 Python 需要安装哪些软件?

    自动配置.有效求助.协作编程.版本控制.一站式解决 Python 新手练习中的痛点. 痛点 这个学期,我在北得克萨斯大学(University of North Texas)教 INFO 5731: ...

  6. catch之后的代码什么时候执行

    1.若catch(){}块中,如果有throw 语句,则,try{}catch(){} finally{}块之外的代码不执行: 否则,执行. 2.try{}中有异常,则异常下面代码不执行. 3.fin ...

  7. Ngnix01

    Nginx(一)------简介与安装   目录 1.Nginx 的简介 2.Nginx 的常用功能 3.Nginx 安装 ①.下载地址 ②.Windows 版本安装 ③.Linux 版本安装 说到 ...

  8. vue 中v-if 与v-show 的区别

    相同点或者说功能,都可以动态操作dom元素的显示隐藏 不同点: 1.手段:v-if是动态的向DOM树内添加或者删除DOM元素:v-show是通过设置DOM元素的display样式属性控制显隐: 2.编 ...

  9. idea2019注册码,亲测可用(暂时不可用)!

    原文链接:https://www.jianshu.com/p/702deab2447c 注册码: MNQ043JMTU-eyJsaWNlbnNlSWQiOiJNTlEwNDNKTVRVIiwibGlj ...

  10. java前后端开发需掌握的框架及技术

    一.Java开发 1.J2EE架构及主流框架,spring4.spring boot.spring MVC.spring Security.spring cloud.struct2.hibernate ...