查找数组中第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 ...
随机推荐
- python接口测试之读取配置文件
1.python使用自带的configparser模块用来读取配置文件,配置文件可以为.conf或.ini结尾 在使用前需要先安装该模块,使用pip安装即可 2.新建一个名为a.conf的配置文件 a ...
- php使用xpath爬取内容
<?php $html = file_get_contents('https://tieba.baidu.com/f?kw=%C9%EE%BB%A7&fr=ala0&loc=re ...
- php 反射 实例化类
<?php class Person { public $name; public $sex; public function __construct($name,$sex=1) { $this ...
- scrapy 管道里面使用mysql插入数据库 python操作mysql
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to t ...
- 一文读懂Redis常见对象类型的底层数据结构
Redis是一个基于内存中的数据结构存储系统,可以用作数据库.缓存和消息中间件.Redis支持五种常见对象类型:字符串(String).哈希(Hash).列表(List).集合(Set)以及有序集合( ...
- css中伪元素before或after中content的特殊用法attr【转】
[原文]https://segmentfault.com/a/1190000002750033 CSS中主要的伪元素有四个:before/after/first-letter/first-line,在 ...
- CSDN的Markdown编辑器实用技巧(傻瓜式教程)
markdown编辑器被很多人声称是可以取代word的文字编辑器,其优点我们在这就不再过多赘述了,但对于一些初次接触的人来说,或多或少都有还些不适应,其主要原因在于一些常见的功能突然不知道怎么实现,所 ...
- 分布式消息系统之Kafka集群部署
一.kafka简介 kafka是基于发布/订阅模式的一个分布式消息队列系统,用java语言研发,是ASF旗下的一个开源项目:类似的消息队列服务还有rabbitmq.activemq.zeromq:ka ...
- RPM与YUM使用
1.RPM 1.1RPM简介 RPM全名RedHat Package Manager 优点: 1. 由于已经编译完成并且打包完毕,所以软件传输与安装上很方便 (不需要再重新编译): 2. 由于软件的信 ...
- RateLimiter的 SmoothBursty(非warmup预热)及SmoothWarmingUp(预热,冷启动)
SmoothBursty 主要思想 记录 1秒内的微秒数/permitsPerSencond = 时间间隔interval,每一个interval可获得一个令牌 根据允许使用多少秒内的令牌参数,计算出 ...