获取一个数组里面第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 ...
随机推荐
- java点滴之MulticastSocket的使用
一基本概念 该类恰是上文介绍的DatagramSocket的子类. DatagramSocket仅仅同意数据报发送给指定的目标地址,而MulticastSocket能够将数据报以广播的方式发送到多个c ...
- vue父子组件之间的传值
引入组件 父组件 <div> <form-edit></form-edit> </div> import FormEdit from "路径& ...
- vue组件中,iview的modal组件爬坑--modal的显示与否应该是使用v-show
这是我第一次写博客,主要是记录下自己解决问题的过程和知识的总结,如有不对的地方欢迎指出来! 需求:点击btn,弹出modal显示图表(以折现图为例) 这应该是很基本的需求也是很容易实现的,代码和效果如 ...
- 『C++』Temp_2019_03_14 不同类的循环引用
#include <iostream> #include <string> #include <regex> using namespace std; //提前声明 ...
- 前端提交表单两种验证方式记录 jq或h5 required属性
JQuery: <form id="form"> <input type="text" name="aaa"> &l ...
- react脚手架环境搭建流程
1.安装与配置node.js:1.1软件下载地址:https://nodejs.org/en/,推荐下载.msi文件,其中npm已经集成在了node.js中.1.2 双击下载的.msi文件进行安装,安 ...
- 07.centos7构建 IntelliJ IDEA(简称IDEA)开发环境
一.安装IDEA 进入官网下载linux版的社区便,IDEA分为社区版和旗舰版,社区版免费,并且基本满足spark开发需求. 解压安装 目录为/opt/idea 注意:centos命令行界面下是无法安 ...
- KKT原理以及SVM数学的理论推导分析
一直很好奇机器学习实战中的SVM优化部分的数学运算式是如何得出的,如何转化成了含有内积的运算式,今天上了一节课有了让我很深的启发,也明白了数学表达式推导的全过程. 对于一个SVM问题,优化的关键在于 ...
- 5.18-笨办法学python-习题14
有了习题13的基础,习题14就不是问题了. 这一节主要是一个简单的提示符.提示符就是像">"这个的东西,因为我们之前用input的时候,它是用来让用户输入的,可是平常人并不知 ...
- Hadoop安装配置
1.集群部署介绍 1.1 Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台.以Hadoop分布式文件系统(HDFS,Hadoop Distributed Filesy ...