如何在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大的元素的更多相关文章

  1. [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 ...

  2. 寻找数组中的第K大的元素,多种解法以及分析

    遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...

  3. [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 ...

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

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

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

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

  6. HDU 5249 离线树状数组求第k大+离散化

    KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  7. 算法题之找出数组里第K大的数

    问题:找出一个数组里面前K个最大数. 解法一(直接解法): 对数组用快速排序,然后直接挑出第k大的数.这种方法的时间复杂度是O(Nlog(N)).N为原数组长度. 这个解法含有很多冗余,因为把整个数组 ...

  8. 求一个数组的最大k个数(java)

    问题描写叙述:求一个数组的最大k个数.如,{1,5,8,9,11,2,3}的最大三个数应该是,8,9,11 问题分析: 1.解法一:最直观的做法是将数组从大到小排序,然后选出当中最大的K个数.可是这种 ...

  9. [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 ...

随机推荐

  1. java点滴之MulticastSocket的使用

    一基本概念 该类恰是上文介绍的DatagramSocket的子类. DatagramSocket仅仅同意数据报发送给指定的目标地址,而MulticastSocket能够将数据报以广播的方式发送到多个c ...

  2. vue父子组件之间的传值

    引入组件 父组件 <div> <form-edit></form-edit> </div> import FormEdit from "路径& ...

  3. vue组件中,iview的modal组件爬坑--modal的显示与否应该是使用v-show

    这是我第一次写博客,主要是记录下自己解决问题的过程和知识的总结,如有不对的地方欢迎指出来! 需求:点击btn,弹出modal显示图表(以折现图为例) 这应该是很基本的需求也是很容易实现的,代码和效果如 ...

  4. 『C++』Temp_2019_03_14 不同类的循环引用

    #include <iostream> #include <string> #include <regex> using namespace std; //提前声明 ...

  5. 前端提交表单两种验证方式记录 jq或h5 required属性

    JQuery: <form id="form"> <input type="text" name="aaa"> &l ...

  6. react脚手架环境搭建流程

    1.安装与配置node.js:1.1软件下载地址:https://nodejs.org/en/,推荐下载.msi文件,其中npm已经集成在了node.js中.1.2 双击下载的.msi文件进行安装,安 ...

  7. 07.centos7构建 IntelliJ IDEA(简称IDEA)开发环境

    一.安装IDEA 进入官网下载linux版的社区便,IDEA分为社区版和旗舰版,社区版免费,并且基本满足spark开发需求. 解压安装 目录为/opt/idea 注意:centos命令行界面下是无法安 ...

  8. KKT原理以及SVM数学的理论推导分析

    一直很好奇机器学习实战中的SVM优化部分的数学运算式是如何得出的,如何转化成了含有内积的运算式,今天上了一节课有了让我很深的启发,也明白了数学表达式推导的全过程. 对于一个SVM问题,优化的关键在于 ...

  9. 5.18-笨办法学python-习题14

    有了习题13的基础,习题14就不是问题了. 这一节主要是一个简单的提示符.提示符就是像">"这个的东西,因为我们之前用input的时候,它是用来让用户输入的,可是平常人并不知 ...

  10. Hadoop安装配置

    1.集群部署介绍 1.1 Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台.以Hadoop分布式文件系统(HDFS,Hadoop Distributed Filesy ...