1. 程式人生 > >在無序陣列中找到第k大的數

在無序陣列中找到第k大的數

在N個元素中查詢第K大元素,一般比較簡單的方法就是先快速排序,然後直接返回array[N - K]或者利用掃描法,每一次掃描都找到當前陣列中最大的元素,這個其實就是部分氣泡排序。前一種演算法的時間複雜度是O(NlogN),後一種演算法的時間複雜度是K*N。當然,這裡我們不打算具體討論以上兩種方案,接下來看看其他方法。

       第一種方法:利用堆排序的思想來查詢陣列中第K大元素。首先提取子陣列array[0...K-1]並構造小頂堆,然後把剩下子陣列array[K...N-1]中的所有元素與堆頂元素array[0]進行比較,若大於堆頂元素,則進行交換並重新構造子陣列array[0...K-1]使其滿足小頂堆的要求。這樣的話,最後子陣列array[0...K-1]就是N個元素中的前K個最大元素,堆頂array[0]就是N個元素中的第K大元素。具體實現程式碼如下:

  1. #include <cstdlib>
  2. #include <iostream>
  3. usingnamespace std;  
  4. /***************************************************************************** 
  5.  函 數 名  : small_heap_adjust 
  6.  功能描述  : 根據陣列構建小頂堆  
  7.  輸入引數  : array  待調整的堆陣列 
  8.              index  待調整的陣列元素的位置 
  9.              length 陣列的長度 
  10.  輸出引數  : 無
     
  11.  返 回 值  : 無  
  12.  修改歷史      : 
  13.   1.日    期   : 2012/09/10 
  14.     作    者   : liguangting 
  15.     修改內容   :  
  16. *****************************************************************************/
  17. void small_heap_adjust(int *array, int index, int length)  
  18. {  
  19.     int child;  
  20.     int temp = array[index];  
  21.     if (2 * index + 1 >= length)  
  22.     {  
  23.         return;  
  24.     }  
  25.     //子結點位置 = 2 * 父結點位置 + 1
  26.     child = 2 * index + 1;  
  27.     //得到子結點中較小的結點 
  28.     if (child < length - 1 && array[child + 1] < array[child])  
  29.     {  
  30.         ++child;  
  31.     }  
  32.     //如果較小的子結點小於父結點那麼把較小的子結點往上移動,替換它的父結點 
  33.     if (temp > array[child])  
  34.     {  
  35.         array[index] = array[child];  
  36.     }  
  37.     else
  38.     {  
  39.         return;  
  40.     }  
  41.     //最後把需要調整的元素值放到合適的位置 
  42.     array[child] = temp;  
  43.     small_heap_adjust(array, child, length);  
  44. }  
  45. /***************************************************************************** 
  46.  函 數 名  : find_kmax_value 
  47.  功能描述  : 查詢陣列中第K大元素  
  48.  輸入引數  : array  待查詢的陣列  
  49.              length 陣列的長度 
  50.              K      第K大  
  51.  輸出引數  : 無 
  52.  返 回 值  : 返回第K大元素  
  53.  修改歷史      : 
  54.   1.日    期   : 2012/09/10 
  55.     作    者   : liguangting 
  56.     修改內容   :  
  57. *****************************************************************************/
  58. int find_kmax_value(int *array, int length, int k)  
  59. {  
  60.     int i = 0;  
  61.     //把子陣列array[0...k-1]構造成小頂堆 
  62.     for (i = k / 2 - 1; i >= 0; i--)  
  63.     {  
  64.         small_heap_adjust(array, i, k);  
  65.     }  
  66.     //子陣列array[k...length-1]的所有元素與堆頂元素進行比較,若大於堆頂元素
  67.     //則交換,並重新調整堆 
  68.     for (i = k; i < length; i++)  
  69.     {  
  70.         if (array[i] > array[0])  
  71.         {  
  72.             swap(array[0], array[i]);  
  73.             small_heap_adjust(array, 0, k);  
  74.         }  
  75.     }  
  76.     return array[0];  
  77. }  
  78. int main(int argc, char *argv[])  
  79. {  
  80.     constint LENGTH = 100;  
  81.     constint K = 30;  
  82.     int array[LENGTH] = {0};  
  83.     int kmax = 0;  
  84.     srand(time(NULL));  
  85.     cout << "原始陣列:" << endl;   
  86.     for (int i = 0; i < LENGTH; i++)  
  87.     {  
  88.         array[i] = rand() % 100;  
  89.         cout << array[i] << " ";  
  90.         if (0 == (i + 1) % 10)  
  91.         {  
  92.             cout << endl;  
  93.         }  
  94.     }  
  95.     kmax = find_kmax_value(array, LENGTH, K);  
  96.     cout << "第K大元素:" << kmax << endl;  
  97.     sort(array, array + LENGTH);  
  98.     cout << "排序後陣列:" << endl;  
  99.     for (int i = 0; i < LENGTH; i++)  
  100.     {  
  101.         cout << array[i] << " ";  
  102.         if (0 == (i + 1) % 10)  
  103.         {  
  104.             cout << endl;  
  105.         }  
  106.     }  
  107.     if (kmax == array[LENGTH - K])  
  108.     {  
  109.         cout << "查詢第K大元素成功!" << endl;  
  110.     }  
  111.     system("PAUSE");  
  112.     return EXIT_SUCCESS;  
  113. }  


       第二種方法:同樣是利用堆排序的思想,但採用的是大頂堆,並且結合部分排序的思想。大致思路:首先把陣列array[0...N-1]構造成大頂堆,然後依次提取當前堆中最大的元素,直到找到第K大元素。具體實現程式碼如下:

  1. /***************************************************************************** 
  2.  函 數 名  : big_heap_adjust 
  3.  功能描述  : 根據陣列構建大頂堆  
  4.  輸入引數  : array  待調整的堆陣列 
  5.              index  待調整的陣列元素的位置 
  6.              length 陣列的長度  
  7.  輸出引數  : 無 
  8.  返 回 值  : 無  
  9.  修改歷史      : 
  10.   1.日    期   : 2012/09/10 
  11.     作    者   : liguangting 
  12.     修改內容   :  
  13. *****************************************************************************/
  14. void big_heap_adjust(int *array, int index, int length)  
  15. {  
  16.     int child;  
  17.     int temp = array[index];  
  18.     if (2 * index + 1 >= length)  
  19.     {  
  20.         return;  
  21.     }  
  22.     //子結點位置 = 2 * 父結點位置 + 1
  23.     child = 2 * index + 1;  
  24.     //得到子結點中較大的結點 
  25.     if (child < length - 1 && array[child + 1] > array[child])  
  26.     {  
  27.         ++child;  
  28.     }  
  29.     //如果較大的子結點大於父結點那麼把較大的子結點往上移動,替換它的父結點 
  30.     if (temp < array[child])  
  31.     {  
  32.         array[index] = array[child];  
  33.     }  
  34.     else
  35.     {  
  36.         return;  
  37.     }  
  38.     //最後把需要調整的元素值放到合適的位置 
  39.     array[child] = temp;  
  40.     big_heap_adjust(array, child, length);  
  41. }  
  42. /***************************************************************************** 
  43.  函 數 名  : find_kmax_value 
  44.  功能描述  : 查詢陣列中第K大元素  
  45.  輸入引數  : array  待查詢的陣列  
  46.              length 陣列的長度 
  47.              K      第K大  
  48.  輸出引數  : 無 
  49.  返 回 值  : 返回第K大元素  
  50.  修改歷史      : 
  51.   1.日    期   : 2012/09/10 
  52.     作    者   : liguangting 
  53. 相關推薦

    尋找無序陣列K大數和前K大數

    兩個問題互相可以轉化。如果可以找到第K大數,那麼只再需要O(N)就可以找齊剩餘的前K大數。如果可以找到前K大數,那麼只再需要O(K)就可以找到第K大數。 先排序,在找第K個。O(NlgN) 快速排序的思想,可以做到平均效率O(N) 隨機選一個元素,把所有小於等於這個元素

    經典演算法題:無序整數陣列k大的數

    經典問題:寫一段程式,找出陣列中第k大的數,輸出數所在的位置。 【解法一】先排序,然後輸出第k個位置上的數 我們先假設元素的數量不大,例如在幾千個左右,在這種情況下,那我們就排序一下吧。在這裡,快速排序或堆排序都是不錯的選擇,他們的平均時間複雜度 都是 O(N * logN

    python:無序陣列尋找K大的元素

    題目: 所謂“第(前)k大數問題”指的是在長度為n(n>=k)的亂序陣列中S找出從大到小順序的第(前)k個數的問題。 解法1:堆排序 採用元素下沉法,維護一個k大小的最小堆,對於陣列中的每一

    兩個排序陣列k大的數

    一、問題給定兩個已經排序好的陣列,找到兩者所有元素中第k大的元素二、解法一:merge--將兩個有序陣列變成一個有序陣列時間複雜度O(m+n),空間複雜度O(m+n)/************************************************* 給定兩個

    基於快排實現,在N個亂序的陣列K大的數(Java實現)

    類似於快速排序,執行一次快速排序之後,每次只選擇一部分繼續執行快速排序,直到找到第K大個元素為止,這個元素在陣列位置後面的元素即為所求。 時間複雜度:O(n) 利用快排的思想,從陣列arr中隨機找出一個元素X,把陣列分成兩部分arr_a和arr_b。 arr_a中的元素比x大,arr_b中的元素比x小。 這

    無序陣列找到k大的數

    在N個元素中查詢第K大元素,一般比較簡單的方法就是先快速排序,然後直接返回array[N - K]或者利用掃描法,每一次掃描都找到當前陣列中最大的元素,這個其實就是部分氣泡排序。前一種演算法的時間複雜度是O(NlogN),後一種演算法的時間複雜度是K*N。當然,這裡我們不

    無序陣列找到K 大的元素

    當然如果我們想要實現這個問題會有很多思路,可以將原來的陣列進行排序即可,直接隨機訪問到第K個元素即可。 我們專門寫一篇部落格當然不是想利用這種思路的,可以試試改進的快速排序啊,對不,我個人覺得是利用了兩種思路一個是快速排序一個是二分查詢,在進行快速排序的時候,在指定範圍內找

    java 實現從無序陣列 k大的數, 無序陣列充許有重複元素

    要求找出第幾名的元素是什麼(找出B[i]的值)? 找出第k名的元素的值。          先從A中隨機一個下標index1, 然後進行一趟快速排序等到新陣列A1,排完了就知道index1對應的元素在A1中的新下標index2. 如果k等於index2,則A1[index2]就是要找的值。 如果 k小於in

    Day06--陣列K個最大元素

    class Solution: def findKthLargest(self, nums, k): """ :type nums: List[int] :type k: int :rtype: int

    leetcode 215. 陣列K個最大元素(Medium)(陣列)

    題目: 在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出: 5 示例 2: 輸入: [3,2,3,1,

    LeetCode 215——陣列 K 個最大元素

    1. 題目 在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出: 5 示例 2: 輸入: [3,

    LeetCode題解 | 215. 陣列K個最大元素

    在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出: 5 示例 2: 輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4 輸出: 4 說明:

    LeetCode 215. 陣列K個最大元素 Kth Largest Element in an Array

    題目描述:就是在陣列中找到第k大的數 (1)第一種方法就是利用sort函式排序 時間複雜度 O(NlogN),空間複雜度 O(1) public int findKthLargest(int[] nums, int k) { Arrays.sort(nums); r

    【LeetCode】215. 陣列K個最大元素 結題報告 (C++)

    原題地址:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/submissions/ 題目描述: 在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不

    leetcode 215 陣列k個最大的元素

    在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1:輸入: [3,2,1,5,6,4] 和 k = 2  輸出: 5示例 2:輸入: [3,2,3,1,2,4,5

    Leetcode---陣列K個最大元素--隨機化演算法

    陣列中的第K個最大元素 題目連結:陣列中的第K個最大元素 思路: 如果先排序,不管利用哪個,比較排序時間複雜度最優為O(nlgn) 但是我們發現,快排的一趟排列有一定的性質,我們可以求得一趟快排之後,該數在整個陣列中排在第幾位,且將整個陣列劃分為兩段 利用這個

    LeetCode 215. 陣列K個最大元素 Python3

    在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出: 5

    陣列K個最大元素

    在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出:

    陣列K個最大元素 【LeetCode 排序】

    在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2輸出: 5 示例 2: 輸入: [3,2,3,1,2,4,5,5,6] 和 k

    LeetCode-215. 陣列K個最大元素

    題目 在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。 示例 1: 輸入: [3,2,1,5,6,4] 和 k = 2 輸出: 5 示例 2: 輸入: [3,2,3,1,2,4,5,5,6]