获取一个数组里面第K大的元素
如何在O(n)内获取一个数组比如{9, 1, 2, 8, 7, 3, 6, 4, 3, 5, 0, 9, 19, 39, 25, 34, 17, 24, 23, 34, 20}里面第K大的元素呢?
我们可以使用类似快排的分区方式,将第K大的元素限定在数组的左边或右边,递归求取。
我的Java代码实现如下:
package com.structure.sort; /**
* @author zhangxingrui
* @create 2019-01-27 22:52
**/
public class QuickSort { public static void main(String[] args) {
int[] numbers = {9, 1, 2, 8, 7, 3, 6, 4, 3, 5, 0, 9, 19, 39, 25, 34, 17, 24, 23, 34, 20};
// int[] numbers = {3,1,2};
// 快速排序借助递归来实现,重要的是要找到递归的终结条件(不然容易发生堆栈异常)
// 递推公式:quickSort(p...r) = merge(p, q - 1) + merge(q+1, r)
// 终结条件:p >= r
/*quickSort(numbers, 0, numbers.length - 1);
for (int number : numbers) {
System.out.println(number);
}*/ int k = getK(4, numbers, 0, numbers.length - 1);
System.out.println(k);
} private static void quickSort(int[] numbers, int p, int r){
if(p >= r)
return;
int q = partition(numbers, p, r, false);
quickSort(numbers, p, q - 1);
quickSort(numbers, q + 1, r);
} /**
* @Author: xingrui
* @Description: 分区
* @Date: 23:13 2019/1/27
*/
private static int partition(int[] numbers, int p, int r, boolean isAsc){
int k = numbers[r];
int i = p; if(isAsc){
for (int j = p; j <= r; ++j) {
if(numbers[j] < k){
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
i++;
}
}
numbers[r] = numbers[i];
numbers[i] = k;
return i;
}else{
for (int j = p; j <= r; ++j) {
if(numbers[j] > k){
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
i++;
}
}
numbers[r] = numbers[i];
numbers[i] = k;
return i;
} } /**
* @Author: xingrui
* @Description: 获取第K大的元素
* @Date: 23:15 2019/1/29
*/
private static int getK(int k, int[] numbers, int p, int r){
int q = partition(numbers, p, r, false); if(q + 1 == k)
return numbers[q]; if(q + 1 > k){
return getK(k, numbers, p, q - 1);
}else{
return getK(k, numbers, q + 1, r);
}
} }
原理就是我们先任取一个数作为分区的数,把大于它的数放在它的左边,小于它的数放在它的右边。
假设我们有数组array[p...r],那么第一次分区之后就形成了array[p...q-1],q,array[q+1...r]三个部分,如果我们要求取第3大的元素,
那么就将3与q+1做比较,
如果3==q+1,那么说明array[p...q-1]里面只有两个元素且都>array[q],而array[q+1,r]都<q,所以array[q]
就是第三大的元素;
如果3 > q+1,说明array[p...q-1]里面的元素只有一个元素,所以我们需要到array[q+1...r]里面再去找;
如果3 < q+1,则说明array[p...q-1]里面有三个元素,所以我们还需要到array[p...q-1]里面去找。
这样的话,每次只会到分区的一半的数组里面去找:n/2 + n/4 + n/8 + 直到区间缩小为1,最终可得2n - 1,
所以这样做的时间复杂的就是O(n)。
获取一个数组里面第K大的元素的更多相关文章
- [leetcode]215. Kth Largest Element in an Array 数组中第k大的元素
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- 寻找数组中的第K大的元素,多种解法以及分析
遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...
- [LeetCode] Kth Largest Element in an Array 数组中第k大的数字
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- 寻找数组中第K大的数
给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...
- [经典算法题]寻找数组中第K大的数的方法总结
[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...
- HDU 5249 离线树状数组求第k大+离散化
KPI Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 算法题之找出数组里第K大的数
问题:找出一个数组里面前K个最大数. 解法一(直接解法): 对数组用快速排序,然后直接挑出第k大的数.这种方法的时间复杂度是O(Nlog(N)).N为原数组长度. 这个解法含有很多冗余,因为把整个数组 ...
- 求一个数组的最大k个数(java)
问题描写叙述:求一个数组的最大k个数.如,{1,5,8,9,11,2,3}的最大三个数应该是,8,9,11 问题分析: 1.解法一:最直观的做法是将数组从大到小排序,然后选出当中最大的K个数.可是这种 ...
- [LeetCode] 215. Kth Largest Element in an Array 数组中第k大的数字
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
随机推荐
- PAT——1019. 数字黑洞
给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有“数字黑洞”之称的6174 ...
- ASP.NET Core 中的 WebSocket 支持(转自MSDN)
本文介绍 ASP.NET Core 中 WebSocket 的入门方法. WebSocket (RFC 6455) 是一个协议,支持通过 TCP 连接建立持久的双向信道. 它用于从快速实时通信中获益的 ...
- oracle 子查询的几个种类
1.where型子查询: select cat_id,good_id,good_name from goods where good_id in (selct max(good_id) from go ...
- vue+echarts实现可拖动节点的折现图(支持拖动方向和上下限的设置)
本篇文档主要是利用echarts实现可拖动节点的折现图,在echarts中找到了一个demo,传送门:https://echarts.baidu.com/examples/editor.html?c= ...
- Vector/Push_back
https://bbs.csdn.net/topics/370225285 https://blog.csdn.net/u013630349/article/details/46853297 http ...
- cookie的简单认识
1.cookie Cokie又叫会话跟踪技术,实际上就是客户端硬盘上的一个文本文件,该文件用来存储一些数据. 首先,HTTP请求时无状态的,也就是说,你打开一个网页和下一个网页之间没有任何关系,数据不 ...
- node.js的http模块创建基本Web服务器
首先下载node.js模块.终端执行命令 npm i node -g 引入http核心模块 const http =require('http') 引入文件系统模块 const fs =require ...
- python写员工信息表作业笔记
需求 流程图
- Quick find Helper
using System; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; /// <summary> /// 视图 ...
- 大数据学习--day17(Map--HashMap--TreeMap、红黑树)
Map--HashMap--TreeMap--红黑树 Map:三种遍历方式 HashMap:拉链法.用哈希函数计算出int值. 用桶的思想去存储元素.桶里的元素用链表串起来,之后长了的话转红黑树. T ...