TopK问题有几种解决办法?-创新互联

TopK问题的描述:

指定n个数字,找出其中大的k个数,这就是经典的TopK问题

公司主营业务:成都网站建设、做网站、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联公司是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联公司推出友好免费做网站回馈大家。
解决方法一:全局排序
  • 将n个数进行全排序,取出大的k个,即是所需的结果
  • 代码:
    public int[] topK(int[] array, int k) {
       Arrays.sort(array);
       return Arrays.copyOfRange(array, array.length - k, array.length);
    }
  • 时间复杂度是O(N*logN)
解决方法二:局部排序
  • 其实没有必要将所有的元素都排序,只需要将前k个大的值排序出来就可以停止排序,得到的k个值就是需要的结果
  • 代码
    public int[] topK(int[] array, int k) {
       for(int i = 0; i < k; i++) {
         for(int j = array.length - 1; j > 0; j--) {
           if(array[j] > array[j - 1]) {
             int tmp = array[j];
             array[j] = array[j - 1];
             array[j - 1] = tmp;
           }
         }
       }
    }
  • 时间复杂度是O(k*N)
解决方法三:堆
  • 构建一个k大小的小堆,先将前k个元素放入堆中,然后遍历剩下的元素,如果大于堆顶的元素,就和堆顶的元素进行交换,遍历结束后,得到的堆上的值就是前k个大的值
  • 代码
    public Integer[] topK(int[] array, int k) {
       PriorityQueue queue = new PriorityQueue<>();
       for(int i = 0; i < k; i++) {
         queue.add(array[i]);
       }
       for(int i = k; i < array.length; i++) {
         if(array[i] > queue.peek()) {
           queue.poll();
           queue.add(array[i]);
         }
       }
       return (Integer[])queue.toArray();
    }
  • 时间复杂度:O(N*logK)
解决方法四:随机选择
  • 使用减治的的思想,制定一个元素flag将比flag大的元素放在他左边,比他小的放在他右边
  • 如果flag的的下标index比k大说明前k个大的元素都在flag左边的区间,然后在他左区间内重复第一步直到找到下标为k的值
  • 如果flag的下标index比k小说明只要在他的右区间内重复第一步找到下标为k-index的值
  • 找到第k个大的值后再进行此一步骤,它左边的所有的元素就是前k个大的值
  • 代码:

    public int[] topK5(int[] array, int k) {
       int left = 0;
       int right = array.length - 1;
       //因为数组下标是以0开始的,因此第k个的小标为k - 1,因此传入的为k - 1
       int flag = RS(array, left, right, k - 1);
       //返回值flag为第k个大值的下标,因此需要前k个大的值时,拷贝数组的范围是[0, flag + 1)
       return Arrays.copyOfRange(array, 0, flag + 1));
    }
    
    private int RS(int[] array, int left, int right, int k) {
       if (left >= right) {
         return left;
       }
    
       int index = partition(array, left, right);
       int temp = index - left;
    
       if(temp >= k) {
         return RS(array, left, index - 1, k);
       } else {
         return RS(array, index + 1, right, k - index);
       }
    }
    
    private int partition(int[] array, int left, int right) {
       int tmp = array[left];
       int l = left;
       int r = right;
    
       while(l < r) {
         while(l < r && array[r] <= tmp) {
           r--;
         }
         array[l] = array[r];
         while(l < r && array[l] >= tmp) {
           l++;
         }
         array[r] = array[l];
       }
       array[l] = tmp;
       return l;
    }
  • 时间复杂度:O(N)

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享题目:TopK问题有几种解决办法?-创新互联
标题网址:http://azwzsj.com/article/digedh.html