zoukankan      html  css  js  c++  java
  • 数据结构--BFPRT算法(TOP-K算法)

    在一大堆数中求其前k大或前k小的问题

    最坏时间复杂度为O(n)

    1.可以将数组排序,然后取出第k小的数   O(nlogn)

    2.维护一个k大小的堆    O(nlogk)

    public static class MinHeapComparator implements Comparator<Integer> {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        }
        /**
         * 维护一个小根堆,每次都是从小根堆取值
         * @param arrays
         * @param k
         * @return
         */
        public static int[] smallOfKByHeap(int[] arrays, int k) {
            if (k == 0 || arrays == null || arrays.length == 0) return null;
    
            PriorityQueue<Integer> queue = new PriorityQueue<>( new MinHeapComparator() );
    
            for(int i = 0; i < arrays.length; i++){
                queue.add( arrays[i] );
            }
    
            int[] res = new int[k];
            for(int i = 0; i < k; i++){
                res[i] = queue.poll();
            }
            return res;
        }
    

      

    3.一种比较简单的方法:采用荷兰国旗的partition解法,随机(int random = (int)(Math.random() * (right - left + 1)) + left)选取一个数num,进行partition,然后看k在三个区域的哪一部分,在=num区域,则直接返回,若在另外两个区域,则只求解其中的一半即可,依然采取如下的策略  长期期望 O(N)  取决于每次选取的num的位置

    public static int smallOfKByPartition(int[] arrays, int k){
            if(k == 0 || arrays == null || arrays.length == 0) return -1;
            int num = smallK( arrays, 0, arrays.length - 1, k - 1 );
            return num;
        }
    
        public static int smallK(int[] arrays, int left, int right, int k){
            if(left == right) return arrays[left];
            int[] num = partition( arrays, left, right);
    
            if(num[0] <= k && num[1] >= k){
                return arrays[k];
            } else if(num[0] > k){
                return smallK( arrays, left, num[0] - 1, k);
            } else{
                return smallK( arrays, num[1] + 1, right, k);
            }
        }
    
        public static int[] partition(int[] arrays, int left, int right){
            int random = (int) (Math.random() * (right - left + 1)) + left;
            swap(arrays, random, right);
    
            int index = left;
            int small = left - 1, big = right;
            while(index < big){
                if(arrays[index] < arrays[right]){
                    swap(arrays, ++small, index++);
                } else if(arrays[index] == arrays[right]){
                    index++;
                } else {
                    swap(arrays, index, --big);
                }
            }
    
            swap(arrays, right, big);
            return new int[]{small + 1, big};
        }
    
        public static void swap(int[] arrays, int i, int j){
            int temp = arrays[i];
            arrays[i] = arrays[j];
            arrays[j] = temp;
        }
    <num =num >num

    4.BFPRT算法:  O(N)    bfprt(array, k)

    ①将整个数组array[]  5个5个分组,共有n/5组              O(1)

    ②在组内使用插入排序                          O(N)

    ③找到每个组的中位数,组成新的数组(长度为n/5) newArray[]       O(N)

    ④递归调用bfprt(newArray, newArray.length/2)  求出其中位数  num    T(N/5)

    ⑤然后利用num进行3方法中进行partition,             O(N)            

    <num =num >num

    ⑥若在=num区域时,则返回,否则,选择其中的一半进行后续的partition  T(7N/10)

    T(N) = T(N/5) + T(7N/10) + O(N) = O(N)

  • 相关阅读:
    第十四周 Leetcode 315. Count of Smaller Numbers After Self(HARD) 主席树
    POJ1050 To the Max 最大子矩阵
    POJ1259 The Picnic 最大空凸包问题 DP
    POJ 3734 Blocks 矩阵递推
    POJ2686 Traveling by Stagecoach 状态压缩DP
    iOS上架ipa上传问题那些事
    深入浅出iOS事件机制
    iOS如何跳到系统设置里的各种设置界面
    坑爹的私有API
    业务层网络请求封装
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8984211.html
Copyright © 2011-2022 走看看