如何在百万级数据中找到第K大的数据

假设数组为arr,求第k大元素

思想:利用快排思想,对数组先进行一趟快排,将数组进行分区arr[0...p-1],arr[p],arr[p+1,arr.length-1](p是索引元素的下标),紧接着判断p+1与k的关系,如果p+1=k,那么arr[p]就是第k大元素,如果p+1<k,则对arr[p+1,arr.length-1]进行上述操作,反之对arr[0,p-1]进行上述操作

时间复杂度分析:

* 第一次分区查找,我们需要对大小为 n 的数组执行分区操作,需需要遍历 n 个元素。第二次分区查
* 找,我们只需要对大小为 n/2 的数组执行分区操作,需要遍历n/2 个元素。依次类推,分区遍历
* 元素的个数分别为n、n/2、n/4、n/8、n/16.……直到区间缩小为 1*
* 如果我们把每次分区遍历的元素个数加起来,就是:n+n/2+n/4+n/8+…+1。这是一个等比数列求和,最后的和等于 2n-1* 所以,上述解决思路的时间复杂度就为 O(n)
*
* 利用快排分区的思路:数组按降序排序的方式获取每次provt[i]的坐标来进行判断

实现代码如下:

public class ApplicationQuickSort {

    public static void main(String[] args) {
        int[] arr = {2,5,8,6,4,1,2,4,1,4,10,1,5,4,1,4,5,1,-2,5,2,4,5,5,2,100,4};
        int t = Partition(arr,0,arr.length-1);
        System.out.println(t);
        int k = 1;
        while(t+1!=k){
            if(t+1<k){
                t = Partition(arr,t+1,arr.length-1);
            }else if(t+1>k){
                t = Partition(arr,0,t-1);
            }
        }
        System.out.println(arr[t]);
    }

    public static int Partition(int[] arr,int start,int end){
        if(start<end){
            int tmp = arr[start];
            while(start<end){
                int t = 0;
                while(tmp >= arr[end]&&start<end){
                    end--;
                }
                if(start<end){
                    arr[start] = arr[end];
                    start++;
                }
                while(arr[start] >= tmp&&start<end){
                    start++;
                }
                if(start<end){
                    arr[end] = arr[start];
                    end--;
                }

            }
            arr[start] = tmp;
            return start;
        }
        return -1;
    }
}
原文地址:https://www.cnblogs.com/du001011/p/11167603.html