2.4 选择第k大的元素 selection
1.目标:找到N个元素中,第k大的数。
例如:max是k=N--1;min是k=0;median是k=N/2
2.Quick-select 借鉴了快速排序的思想
(1)利用partition保证:
①a[j] is in place
②左边的元素不大于a[j],右边的元素不小于a[j]
(2)在其中一个子数组中重复划分,当j=k时结束

3.实现
package com.cx.sort;
public class QuickSelect {
public static Comparable select(Comparable[] a,int k) {
//打乱数组,避免出现最坏情况,平方时间
Shuffling.sort(a);
int lo=0,hi=a.length-1;
while(hi>lo) {
//j in place
int j=partition(a, lo, hi);
//如果j<k,只需要重新划分右边的数组
if(j<k) lo=j+1;
//如果j>k,只需要重新划分左边的数组
else if(j>k) hi=j-1;
else return a[k];
}
return a[k];
}
//划分,使得j左边的数不大于a[j],j右边的数不小于a[j]
private static int partition(Comparable[] a,int lo,int hi) {
int i=lo,j=hi+1;
//1.repeat
while(true) {
//1)循环i,直到大于a[lo]
while(less(a[++i], a[lo]))
//不可少,防止出现dcba时,i越界
if(i==hi) break;
//2)循环j,直到小于a[lo]
while(less(a[lo], a[--j]))
if(j==lo) break;
//3)判断是否交叉
if(i>=j) break;
exch(a, i, j);
}
//2.交叉后,交换lo,j
exch(a, lo , j);
//j in place
return j;
}
private static boolean less(Comparable v,Comparable w) {
return v.compareTo(w)<0;
}
private static void exch(Comparable[] a,int i ,int j ) {
Comparable t=a[i];
a[i]=a[j];
a[j]=t;
}
private static void show(Comparable[] a) {
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
String a[]= {"s","o","r","t","e","x","a","m","p","l","e"};
show(a);
//第几大的数(k=0..N-1)
int k=3;
System.out.println("第"+k+"大的数是:"+select(a, k));
}
}
package com.cx.sort;
public class Shuffling {
public static void sort(Comparable[] a) {
int N=a.length;
for(int i=1;i<N;i++) {
//第i次迭代,随机找r,r是0-r的随机数
int r=(int)(Math.random()*(i+1));
exch(a, i, r);
}
}
private static boolean less(Comparable v,Comparable w) {
return v.compareTo(w)<0;
}
private static void exch(Comparable[] a,int i ,int j ) {
Comparable t=a[i];
a[i]=a[j];
a[j]=t;
}
private static void show(Comparable[] a) {
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
String a[]= {"s","o","r","t","e","x","a","m","p","l","e"};
show(a);
sort(a);
show(a);
}
}
4.说明:
(1)quick-select:平均花费线性时间,最差的情况是~1/2N2
最差的情况发生在正序或倒序的时候,但是第一步的shuffling可以有效的避免这种情况。
线性时间可以简单的N+1/2N+1/4N+..=~2N
(2)常系数还是相对大了,还需要继续改进算法。
2.4 选择第k大的元素 selection的更多相关文章
- 寻找数组中的第K大的元素,多种解法以及分析
遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...
- LeetCode703 流中第k大的元素
前言: 我们已经介绍了二叉搜索树的相关特性,以及如何在二叉搜索树中实现一些基本操作,比如搜索.插入和删除.熟悉了这些基本概念之后,相信你已经能够成功运用它们来解决二叉搜索树问题. 二叉搜索树的有优点是 ...
- [LeetCode] Kth Largest Element in a Stream 数据流中的第K大的元素
Design a class to find the kth largest element in a stream. Note that it is the kth largest element ...
- 输出数组第k大的元素
用快速排序的思想输出数组第k大的元素: #include<iostream> #include<algorithm> using namespace std; //递归实现:返 ...
- 获取一个数组里面第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大的元素呢? 我 ...
- POJ 2985 Treap平衡树(求第k大的元素)
这题也能够用树状数组做,并且树状数组姿势更加优美.代码更加少,只是这个Treap树就是求第K大元素的专家--所以速度比較快. 这个也是从那本红书上拿的模板--自己找了资料百度了好久,才理解这个Trea ...
- 力扣:丑数II和数组中前K大的元素
数组中的第K个元素 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 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 ...
- 215. Kth Largest Element in an Array【Medium】【找到第 k 大的元素】
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
随机推荐
- Spring MVC 结合Velocity视图出现中文乱码的解决方案
编码问题一直是个很令人头疼的事,这几天搭了一个Spring MVC+VTL的web框架,发现中文乱码了,这里记录一种解决乱码的方案. 开发环境为eclipse,首先,检查Window->pref ...
- sql语句中截取字符串
今天在开发过程中因为要用到合并单元格,在程序里实现了以后,查出来的数据太长,都把格式撑大了,后来想想可以在sql语句查询的时候就截取,就去网上找了一下,挺好用,就转了过来: 合并单元格: /// &l ...
- JavaScript——max-age
https://zhidao.baidu.com/question/391047416053664205.html 页面优化方式之一,延长过期时间.默认max-age=0
- 计算器Pro应用项目源码
本计算器实现了一些简单的功能,可能本身还存在一些缺陷,希望大家提建议,能够改进一下. 源码项目我已经上传到源码天堂那里了:http://code.662p.com/list/11_1.html < ...
- PHP流程控制考察点
php遍历数组的三种方法及各自的区别 php遍历数组的方式主要有三种: for循环 foreach循环 while.list().each()组合循环 其中: for循环只能遍历索引数组,foreac ...
- 高阶函数与接口混入和java匿名类
高阶函数与接口混入和java匿名类. 高阶函数中的组件(参量)函数相当于面向对象中的混入(接口)类. public abstract class Bird { private String name; ...
- CREATE TABLE - 定义一个新表
SYNOPSIS CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name ( { column_name data_ty ...
- 服务器设置禁ping
//设置Linux服务器禁ping!!!终端命令行直接输入 echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all 这个是关闭ping的命令. 如果你想要 ...
- 奇异值分解 SVD 的数学解释
奇异值分解(Singular Value Decomposition,SVD)是一种矩阵分解(Matrix Decomposition)的方法.除此之外,矩阵分解还有很多方法,例如特征分解(Eigen ...
- react入门(下)
react生命周期 1. 组件的三个生命周期状态: * Mount:插入真实 DOM * Update:被重新渲染 * Unmount:被移出真实 DOM2. React 为每个状态都提供了两种勾子( ...