[轉載]尋找兩個有序數組中的第K個數或者中位數

http://blog.csdn.net/realxie/article/details/8078043ios

假設有長度分爲爲M和N的兩個升序數組A和B,在A和B兩個數組中查找第K大的數,即將A和B按升序合併後的第K個數。算法


解法一:數組

使用兩個指針指向A和B的開頭,很容易在O(M+N)的時間內完成,此算法略過。spa


解法二:.net

使用二分的方法。算法思想在代碼註釋中指針

 

  1. #include <iostream>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. using namespace std;  
  5.   
  6.   
  7.   
  8. //Notice : K > 0  
  9. int FindKthElm(int A[], int aBeg, int aEnd, int B[], int bBeg, int bEnd, int k)  
  10. {  
  11.     if (aBeg > aEnd)  
  12.     {  
  13.         return B[bBeg + k - 1];  
  14.     }  
  15.     if (bBeg > bEnd)  
  16.     {  
  17.         return A[aBeg + k - 1];  
  18.     }  
  19.       
  20.     //取中間位置  
  21.     int aMid = aBeg + (aEnd - aBeg)/2;    
  22.     int bMid = bBeg + (bEnd - bBeg)/2;  
  23.       
  24.     //從A和B的開始位置到兩個數組中間位置的元素個數  
  25.     int halfLen = aMid - aBeg + bMid - bBeg + 2;  
  26.       
  27.     if (A[aMid] < B[bMid])  
  28.     {  
  29.         if (halfLen > k)  
  30.         {  
  31.             // 此時在合併的數組中A[aBeg...aMid]和元素必定在B[bMid]的左側,  
  32.             // 即此時第k大的元素必定比B[bMid]這個元素小(嚴格來講不大於)  
  33.             // 故之後沒有必要搜索 B[bMid...bEnd]這些元素  
  34.             return FindKthElm(A, aBeg, aEnd, B, bBeg, bMid - 1, k);  
  35.         }  
  36.         else  
  37.         {  
  38.             // 此時在合併的數組中A[aBeg...aMid]元素必定在B[bMid]的左側,  
  39.             // 因此前K個元素中必定包含A[aBeg...aMid](能夠使用反證法來證實這點)。  
  40.             // 可是沒法判斷A[amid+1...aEnd]與B[bBeg...bEnd]之間的關係,幫須要對他們進行判斷  
  41.             // 此時K就剩下除去A[aBeg...aMid]這些元素,個數爲k - (aMid - aBeg + 1)  
  42.             return FindKthElm(A, aMid + 1, aEnd, B, bBeg, bEnd, k - (aMid - aBeg + 1));  
  43.         }  
  44.     }  
  45.     else  
  46.     {  
  47.         //註釋與上面類似  
  48.         if (halfLen > k)  
  49.         {  
  50.             return FindKthElm(A, aBeg, aMid - 1, B, bBeg, bEnd, k);  
  51.         }  
  52.         else  
  53.         {  
  54.             return FindKthElm(A, aBeg, aEnd, B, bMid + 1, bEnd, k - (bMid - bBeg + 1));  
  55.         }  
  56.     }  
  57. }  
  58.   
  59.   
  60. int main()  
  61. {  
  62.     const int ALen = 11;  
  63.     const int BLen = 5;  
  64.       
  65.     int apos = 0;  
  66.     int bpos = 0;  
  67.     int A[ALen];  
  68.     int B[ALen];  
  69.       
  70.     //生成兩個遞增數組A 和 B  
  71.     for (int i = 1; i <= ALen + BLen; ++i)  
  72.     {  
  73.         if (apos >= ALen)  
  74.         {  
  75.             B[bpos++] = i;  
  76.         }  
  77.         else if (bpos >= BLen)  
  78.         {  
  79.             A[apos++] = i;  
  80.         }  
  81.         else  
  82.         {  
  83.             if (rand()%2 == 1)  
  84.             {  
  85.                 A[apos++] = i;  
  86.             }  
  87.             else  
  88.             {  
  89.                 B[bpos++] = i;  
  90.             }  
  91.         }  
  92.     }  
  93.       
  94.     //輸出A和B的內容  
  95.     for (int i = 0; i < ALen; ++i)  
  96.     {  
  97.         cout <<A[i] <<" ";  
  98.     }  
  99.     cout <<endl;  
  100.     for (int i = 0; i < BLen; ++i)  
  101.     {  
  102.         cout <<B[i] <<" ";  
  103.     }  
  104.     cout <<endl;  
  105.       
  106.     //驗證每一個K是否是正解  
  107.     for (int i = 1; i <= ALen + BLen; ++i)  
  108.     {  
  109.         cout << i <<" : "<<FindKthElm(A, 0 , ALen - 1, B, 0 , BLen - 1, i)<<endl;  
  110.     }  
  111.       
  112.     return 0;  
相關文章
相關標籤/搜索