zoukankan      html  css  js  c++  java
  • 从一组数找第K大元素

    最近做面试题,经常与到一个问题,如何高效的从一组数中找到第K大的元素。

    其实我们最容易想到的肯定是蛮力法。

    1. 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn + k)。

    2.选择排序和冒泡排序算法,即选择k次。(这种算法比较简单,这里就不介绍了)

    3.利用快速排序改进。

    利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
               1). Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
               2). Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)
    但是在考虑快排的最坏情况,即每次快排只淘汰一个元素,时间复杂度为n*(n-1)*...*(n-k) 近似为O(n*k),但然这样的几率很小,我们可以通过随机选取划分元素,而不是固定选取首位元素作为划分元素来减小发生的概率。
     
    4.用O(2*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n + k*logn)
    采用自底向上的构造法,最坏情况的时间复杂度为2(n-log(n+1)),所以构造堆的时间复杂度是线性的。
     
    5.维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n * logk)
     
    6.利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)
     
    下面是第三种利用快拍改进的代码实现。
     1  
     2 //这个是快排代码
     3 void QuickSort(int[] array, int begin, int end) {
     4         if (begin >= end) {
     5             return;
     6         }
     7 
     8         int temp = array[begin];
     9         int i = begin;
    10         int j = end;
    11 
    12         while (i < j) {
    13 
    14             while (i < j && temp <= array[j]) {
    15                 j--;
    16             }
    17             array[i] = array[j];
    18 
    19             while (i < j && temp >= array[i]) {
    20                 i++;
    21             }
    22             array[j] = array[i];
    23         }
    24         array[i] = temp;
    25 
    26         QuickSort(array, begin, i - 1);
    27         QuickSort(array, i + 1, end);
    28     }
     1 //这个是利用快拍改进后的代码
     2 
     3  int findK(int[] array, int begin, int end, int k) {
     4         if (begin > end)
     5             return -1;
     6 
     7         int temp = array[begin];
     8         int i = begin;
     9         int j = end;
    10 
    11         while (i < j) {
    12 
    13             while (i < j && temp >= array[j])
    14                 j--;
    15 
    16             array[i] = array[j];
    17 
    18             while (i < j && temp <= array[i])
    19                 i++;
    20 
    21             array[j] = array[i];
    22         }
    23         array[i] = temp;
    24         if (i == k - 1)
    25             return array[i];
    26 
    27         if (k - 1 < i)
    28             return findK(array, begin, i - 1, k);
    29 
    30         return findK(array, i + 1, end, k);
    31     }
  • 相关阅读:
    商品翻牌效果(纯css)
    3D旋转相册(纯css)
    3D旋转
    前端搜索js
    js打字的效果
    淡入淡出,类似于轮播图
    返回顶部
    java设计模式--状态模式
    java设计模式--抽象工厂模式
    java设计模式--观察者模式
  • 原文地址:https://www.cnblogs.com/yfyzy/p/4420843.html
Copyright © 2011-2022 走看看