數組中第K大的元素總結java
解法1: 咱們能夠對這個亂序數組按照從大到小先行排序,而後取出前k大,總的時間複雜度爲O(n*logn + k)。數組
解法2: 若是k很小,好比第五個最大的數,而整個數組的長度很是的大,那麼,還有一種方法就是,我作k遍找最大的數,每作一遍,就把最大的放在數組的最後面(遍歷一次找出最大的數例如冒泡,選擇排序均可以。),而後減小數組掃描的範圍,就能夠把第k大的數找出來,這樣作的複雜度就是O(K*N),在K很小的狀況下,仍是不錯的。測試
解法3: 利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分爲兩部分Sa和Sb。Sa中的元素大於等於X,Sb中元素小於X。第K大的元素在已排序數組中的下標應爲index(第K大元素)=數組長度-1。記元素X的下標爲index(x),當index(x)= index(第K大元素),表示找到結果,返回。spa
這時有兩種狀況:.net
1. index(x)> index(第K大元素),則繼續在下標index(x)的左邊找code
2. index(x)> index(第K大元素),則繼續在下標index(x)的右邊找htm
解法4: 二分[Smin,Smax]查找結果X,統計X在數組中出現,且整個數組中比X大的數目爲k-1的數即爲第k大數。時間複雜度平均狀況爲O(n*logn)blog
解法5:用O(4*n)的方法對原數組建最大堆,而後pop出k次便可。時間複雜度爲O(4*n + k*logn)排序
解法6:維護一個k大小的最小堆,對於數組中的每個元素判斷與堆頂的大小,若堆頂較大,則無論,不然,彈出堆頂,將當前值插入到堆中。時間複雜度O(n * logk)get
解法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 { public int getIndexK(int[] nums, int left, int right, int k) { int i = left, j = right; while (i < j) { while (nums[j] >= nums[left] && i < j) { j--; } //因此交換結束後,須要爲第一個基準元素找位置,這個位置就是如今i的位置. while (nums[i] < nums[left] && i < j) { i++; } if (i < j) { swap(nums, i, j); } } swap(nums, left, i); if (k == i) { return nums[i]; } else if (k < i) { return getIndexK(nums, left, i - 1, k); } else { return getIndexK(nums, i + 1, right, k); } } //交換數組兩個數的位置 private void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } public int getK(int[] arr, int k) { return getIndexK(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