查找数组中第k大的数
问题: 查找出一给定数组中第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大的数的更多相关文章
- [经典算法题]寻找数组中第K大的数的方法总结
[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...
- 寻找数组中第K大的数
给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...
- 查找无序数组中第K大的数
思路: 利用快速排序的划分思想 可以找出前k大数,然后不断划分 直到找到第K大元素 代码: #include <iostream> #include <algorithm> # ...
- 无序数组中第K大的数
1. 排序法 时间复杂度 O(nlogn) 2. 使用一个大小为K的数组arr保存前K个最大的元素 遍历原数组,遇到大于arr最小值的元素时候,使用插入排序方法,插入这个元素 时间复杂度,遍历是 O( ...
- 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 ...
- 求数列中第K大的数
原创 利用到快速排序的思想,快速排序思想:https://www.cnblogs.com/chiweiming/p/9188984.html array代表存放数列的数组,K代表第K大的数,mid代表 ...
- 无序数组中第Kth大的数
题目:找出无序数组中第Kth大的数,如{63,45,33,21},第2大的数45. 输入: 第一行输入无序数组,第二行输入K值. 该是内推滴滴打车时(2017.8.26)的第二题,也是<剑指of ...
- 前端算法题:找出数组中第k大的数字出现多少次
题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...
- 无序数组求第K大的数
问题描述 无序数组求第K大的数,其中K从1开始算. 例如:[0,3,1,8,5,2]这个数组,第2大的数是5 OJ可参考:LeetCode_0215_KthLargestElementInAnArra ...
随机推荐
- 手撸ORM浅谈ORM框架之基础篇
好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...
- jenkins 构建 job 并获取其状态的实现
目录 BACKGROUND INVESTIGATION I 1. 连续触发的相同 job 构建不会重复入队 2. 连续触发的不同 job 构建会各自入队 3. 参数变动的相同 job 构建将分别入队 ...
- C语言/C++编译环境的设置!有的人还没开始就卡住了!
本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器. 文本编辑器 这将用于输入您的程序.文本编辑器包括 Windows Notepad. ...
- 【UR #2】猪猪侠再战括号序列
UOJ小清新题表 题目摘要 UOJ链接 有一个由 \(n\) 个左括号 "(" 和 \(n\) 个右括号 ")" 组成的序列.每次操作时可以选定两个数 \(l, ...
- 最近集训的图论(思路+实现)题目汇总(内容包含tarjan、分层图、拓扑、差分、奇怪的最短路):
(集训模拟赛2)抢掠计划(tarjan强) 题目:给你n个点,m条边的图,每个点有点权,有一些点是"酒吧"点,终点只能在"酒吧",起点给定,路可以重复经过,但点 ...
- 自定义常用input表单元素三:纯css实现自定义Switch开关按钮
自定义常用input表单元素的第三篇,自定义一个Switch开关,表面上看是和input没关系,其实这里采用的是checkbox的checked值的切换.同样,采用css伪类和"+" ...
- Kibana详细入门教程
Kibana详细入门教程 目录 一.Kibana是什么 二.如何安装 三.如何加载自定义索引 四.如何搜索数据 五.如何切换中文 六.如何使用控制台 七.如何使用可视化 八.如何使用仪表盘 一.K ...
- requests-html添加header
from requests_html import HTMLSession session = HTMLSession() headers = { "User-Agent":&qu ...
- 对于某东平台XX娃娃的用户体验进行(严肃、限速)数据分析
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 本次的爬取目标是某东的一个商品,但从来没有用过,所以本人很好奇.我们就采集这 ...
- C# 获取页面get过来的数据
/// <summary> /// 获取get过来的数据 /// </summary> /// <param name="page"></ ...