码迷,mamicode.com
首页 > 编程语言 > 详细

数组中第K大的元素

时间:2015-09-05 13:52:27      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:

数组中第K大的元素总结

        

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

解法2 如果k很小,比如第五个最大的数,而整个数组的长度非常的大,那么,还有一种方法就是,我做k遍找最大的数,每做一遍,就把最大的放在数组的最后面(遍历一次找出最大的数例如冒泡,选择排序都可以。),然后减少数组扫描的范围,就可以把第k大的数找出来,这样做的复杂度就是O(K*N),在K很小的情况下,还是不错的。

解法3 利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分SaSbSa中的元素大于等于XSb中元素小于X。第K大的元素在已排序数组中的下标应为index(第K大元素)=数组长度-1。记元素X的下标为index(x),当index(x)= index(第K大元素),表示找到结果,返回。

       这时有两种情况:

           1. index(x)> index(第K大元素),则继续在下标index(x)的左边找

           2. index(x)> index(第K大元素),则继续在下标index(x)的右边找

 解法4 二分[Smin,Smax]查找结果X,统计X在数组中出现,且整个数组中比X大的数目为k-1的数即为第k大数。时间复杂度平均情况为O(n*logn)

解法5:用O(4*n)的方法对原数组建最大堆,然后popk次即可。时间复杂度为O(4*n + k*logn)

解法6:维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n * logk)

解法7利用计数排序的思想,,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)。

 像解法3和6应该是比较常见的解法:

    下面是解法3的java代码

package com.wj;

/**
 * Created by wangjia .
 * Date:2015/9/5 0005
 * Time:10:53
 */
public class MaxK {
    /*找到划分点位置*/
    int Sort(int[] arr, int low, int high) {
        int pivot = arr[low]; //这里每次的枢纽元素都取了待排数组的第一个元素,记住是a[low],而不是a[0]
        System.out.println("low-->"+low);
        while (low < high)  //时间复杂度是O(n),n是数组长度
        {
            while (arr[high] >= pivot && low < high){
                high--;
            }
            if(low<high){
                arr[low++] = arr[high];
            }
            while (arr[low] < pivot && low < high){
                low++;
            }
            if(low<high){
                arr[high--] = arr[low];
            }
        }
        arr[low] = pivot;
        System.out.println("low-->"+low);
        return low;
    }

    int QuickSort_K_MAX(int[] arr, int low, int high, int k) {
        if (low >= high) {
            return arr[low];
        }
        int res=0;
        int mid = Sort(arr, low, high); //划分子递归数组
        System.out.println("mid-->"+mid);
        if(mid==k){
            res= arr[mid];
        }else if (mid > k) {
             res=QuickSort_K_MAX(arr, low, mid - 1, k); //左递归
        }else {
             res=QuickSort_K_MAX(arr, mid + 1, high, k); //右递归,一旦右递归mid+1=high,将退化成冒泡,递归深度将变成n,n为数组长度
        }
        return res;
    }

   public  int getK(int[] arr,int k){
        return QuickSort_K_MAX(arr,0,arr.length-1,arr.length-k);
   }
}
//时间复杂度:接近O(N)

测试代码:

package com;

import com.wj.MaxK;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/** 
 * MaxK Tester. 
 * Created by wangjia .
 * Date:09/05/2015
 * Time:$Time
 *
*/ 
public class MaxKTest { 
    private MaxK instance;
    @Before
    public void before() throws Exception { 
        instance=new MaxK();
    }
    @After
    public void after() throws Exception { 
        instance=null;
    }
    @Test
    public void testGetK() throws Exception { 
        int[] arr={4, 5, -1, 2, 3};
        Assert.assertEquals(-1,instance.getK(arr, 5));
        Assert.assertEquals(5,instance.getK(arr, 1));
        Assert.assertEquals(4,instance.getK(arr, 2));
        Assert.assertEquals(3,instance.getK(arr, 3));
        Assert.assertEquals(2,instance.getK(arr, 4));
        int[] arr2={-8,11,4,-2,44,56565,23,-232};

        Assert.assertEquals(56565,instance.getK(arr2, 1));
        Assert.assertEquals(44,instance.getK(arr2, 2));
        Assert.assertEquals(-232,instance.getK(arr2, 8));
    }
}

解法6下次再来。

另外给出一些其他的参考文章:http://blog.csdn.net/beiyeqingteng/article/details/6992290

http://job.xdnice.com/content/BiShiJingYan/2012-11/3971.htm

数组中第K大的元素

标签:

原文地址:http://my.oschina.net/dadou/blog/501303

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!