給定兩個已經排序好的數組,找到兩者所有元素中第 k 大的元素

給定兩個已經排序好的數組,找到兩者所有元素中第 k 大的元素。假設爲A,B都按升序排列。


 方法一:
 直接 merge 兩個數組(即將兩個已排好序的數組合併爲一個排好序的新數組(m+n個元素),然後求第 k 大的元素,時間複雜度爲O(m + n);
可以用一個計數器,記錄當前已經找到第 m 大的元素了。同時我們使用兩個指針 pA 和 pB,分別指向 A 和 B 數組的第一個元素,使用類似於 merge sort 的原理,如果數組 A 當前元素小,那麼 pA++,同時 m++;如果數組 B 當前元素 小,那麼 pB++,同時 m++。最終當 m 等於 k 的時候,就得到了我們的答案,O(k)時間,O(1) 空間。但是,當 k 很接近 m + n 的時候,這個方法時間複雜還是 O(m + n) 。

C++代碼:
int findKthMaxNumOfArrays(int A[],int m,int B[],int n,int k)
{
    int *pA=A;
    int *pB=B;
    int i=0;
    int j=0;
    int cur=0;
    while(i<m&&j<n)            
    {
        if(A[i]<B[j])
        {
            cur++;
            if(cur==k) return A[i];
            i++;
        }
        else 
        {
            cur++;
            if(cur==k) return B[j];
            j++;
        }
    }
    while(i<m)                    
    {
        cur++;
        if(cur==k) return A[i];
        i++;
    }
    while(j<n)                   
    {
        cur++;
        if(cur==k) return B[j];
        j++;
    }
} 
方法二: 由於 A 和 B 都是有序的,利用這裏面的信息,類似於二分查找。時間複雜度可以縮短到
              
假設 A 和 B 的元素個數都大於 k/2,我們將 A 的第 k/2 個元素(即 A[k/2-1])和 B 的第 k/2個元素(即 B[k/2-1])進行比較,
             有以下三種情況(爲了簡化這裏先假設 k 爲偶數,所得到的結
論對於 k 是奇數也是成立的):
                • A[k/2-1] == B[k/2-1]
                • A[k/2-1] > B[k/2-1]
                • A[k/2-1] < B[k/2-1]
              如果 A[k/2-1] < B[k/2-1],意味着 A[0] 到 A[k/2-1 ]的肯定在 A ∪ B 的 top k 元素的範圍內,換句話說,A[k/2-1 ]不可能大於 A ∪                B 的第 k 大元素。因此,我們可以放心的刪除 A 數組的這 k/2 個元素。同理,當 A[k/2-1] > B[k/2-1] 時,可以刪除 B 數組的 k/2              個元素。當 A[k/2-1] == B[k/2-1] 時,說明找到了第 k 大的元素,直接返回 A[k/2-1] 或 B[k/2-1]

           因此,我們可以寫一個遞歸函數。那麼函數終止條件如下:
              • 當 A 或 B 是空時,直接返回 B[k-1] 或 A[k-1];
              • 當 k=1 是,返回 min(A[0], B[0]);
              • 當 A[k/2-1] == B[k/2-1] 時,返回 A[k/2-1] 或 B[k/2-1]

int findKthMaxNumOfArrays(int A[],int m,int B[],int n,int k)
{
if(m>n)
return findKthMaxNumOfArrays(B,n,A,m,k);  //假設m永遠<=n;
if(m==0)
return B[k-1];
if(k==1)
return ((A[0]>=B[0]?B[0]:A[0]));
int k2=k>>1;
int pA=((k2>=m)?m:k2);
int pB=k-pA;
if(A[pA-1]<B[pB-1])
return findKthMaxNumOfArrays(A+pA,m-pA,B,n,k-pA);
else if(A[pA-1]>B[pB-1])
return findKthMaxNumOfArrays(A,m,B+pB,n-pB,k-pB);
else
return A[pA-1];
}
 

方法三、判斷a[mid_a] 與 b[mid_b]的關係(同二類似)
 如果A[mida] < B[mid_b]

 1)k小於等於mida + midb + 1,那麼B數組從mid_b開始就沒有用了,縮小B的搜索範圍
 2)k大於mida + midb + 1, 那麼A數組從low到mid_a開始就沒用了,縮小A的搜索範圍
 3)終止條件是 A搜索完 返回B中元素或者相反




找到兩者所有元素的中位數
int findMedianSortedArrays(int A[], int m, int B[], int n)
    {
        int total = m + n;
        if (total & 0x1) 
            return findKth(A, m, B, n, total / 2 + 1);    //m+n爲奇數
        else
            return (findKth(A, m, B, n, total / 2)
                    + findKth(A, m, B, n, total / 2 + 1)) / 2; //m+n爲偶數
    } 
發佈了31 篇原創文章 · 獲贊 14 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章