[转载]寻找两个有序数组中的第K个数或者中位数

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

假设有长度分为为M和N的两个升序数组A和B,在A和B两个数组中查找第K大的数,即将A和B按升序合并后的第K个数。


解法一:

使用两个指针指向A和B的开头,很容易在O(M+N)的时间内完成,此算法略过。


解法二:

使用二分的方法。算法思想在代码注释中

 

  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;  

posted @ 2013-10-02 12:55  Crazy Eric  阅读(462)  评论(0编辑  收藏  举报