基于快排思想的第(前)k大(小)

算法思路就是根据快排的partition,先随机选择一个分隔元素(或a[0]),将数组分为[小于a[p]的元素] a[p] [大于a[p]的元素],如果这时候n-p+1等于k的话,a[p]就是所求的第k大,否则如果n-p+1>k,那么说明第k大元素应该是在[大于a[p]的元素]里,所以再partition这部分,反之亦然。
一般情况下,算法复杂度应该是 O(N+N/2+N/4+...)=O(N)

public class KthMax {

    static int partition(int[] a,int l,int r){
        int t=a[l];
        while(l<r){
            while(l<r && a[r]>=t){
                r--;
            }
            a[l]=a[r];
            while(l<r && a[l]<t){
                l++;
            }
            a[r]=a[l];
        }
        a[l]=t;
        return l;
    }

    /**
     * 复杂度 O(N+N/2+N/4+...)=O(N)
     * @param a
     * @param k
     */
    static void solve(int[] a,int k){
        int n=a.length;
        int p=partition(a,0,n-1);
        //后面一段的长度
        int len=n-p;
        while(len!=k){
            if(len>k){
                //后面一段大于k,再分
                p=partition(a,p+1,n-1);
            }else{
                p=partition(a,0,p-1);
            }
            len=n-p;
        }
    }

    public static void main(String[] args) {
        int[] a={1,8,6,7,15,11,4,2,13,14,12,10,5,9,3,14,8,8,6,11};
        solve(a,2);
        Sort.print(a);
    }
}
posted @ 2020-02-04 20:56  Keane1998  阅读(196)  评论(0编辑  收藏  举报