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 ... 
随机推荐
- .net简单的fileupload控件上传
			前台代码: <asp:FileUpload ID="FileUpload1" runat="server" /> <asp:Button ID ... 
- windows系统同时安装多个nodejs环境(一键切换)
			由于不同程序对nodejs的环境要求不同,从而导致在单台电脑上开发多个nodejs应用很烦人: 好在gnvm,这个家伙帮我解决了问题 官网: https://github.com/kenshin/gn ... 
- was--创建概要文件(典型)
			1.第一步 2 .创建 3.创建 4 .典型 5 下一步 6 下一步 7.下一步 8.输入用户和密码,下一步 9.下一步 10.下一步 11.下一步 12.下一步 13.下一步 14.创建 ... 
- Java Hello World  错误 找不到或无法加载主类
			Java 有几年没用了 生疏了好多 最近又捡起来 结果第一个Hello World 就在黑窗口内报错! 遇到几个小问题. 1. 安装JDK后 在 CMD 中 执行 java -version 正常 因 ... 
- 关于ubuntu16.04系统无法系统更新的解决
			1.提示系统更新升级,报错 /boot空间不足 2.根据网络,为获得/boot 空间,选择删除多余的内核文件 2.1 查询系统当前内核 ~$dpkg --get-selections |grep li ... 
- CAD插入背景图片(网页版)
			把图片作为背景图片可见但是不能编辑操作. 主要用到函数说明: _DMxDrawX::DrawImageToBackground 绘光栅图到背景.详细说明如下: 参数 说明 BSTR sFileName ... 
- 最小生成树Prim算法 Kruskal算法
			Prim算法(贪心策略)N^2 选定图中任意定点v0,从v0开始生成最小生成树 树中节点Va,树外节点Vb 最开始选一个点为Va,其余Vb, 之后不断加Vb到Va最短距离的点 1.初始化d[v0]=0 ... 
- VS2008 ActiveX(ocx控件)的调试工具ActiveX Control Test Container安装说明
			vs2008中的TSTCON( ActiveX Control Test Container )工具非自动安装,而是作为一个例程提供.所以应找到该例程,并编译: 如vs2008安装在默认路径则 1, ... 
- Domain Adaptation论文笔记
			领域自适应问题一般有两个域,一个是源域,一个是目标域,领域自适应可利用来自源域的带标签的数据(源域中有大量带标签的数据)来帮助学习目标域中的网络参数(目标域中很少甚至没有带标签的数据).领域自适应如今 ... 
- LAME的“命令行”
			VBR 编码 (强烈推荐) Alt Preset Extreme (平均256kbps) 我们有时在网上可以看到".LAME-APX." 就是这种形式,我们也可以在文件名中包含这个 ... 
