兩個有序數組中找中位數或者第K大的元素

RT,在兩個有序數組中找中位數或者第K大的元素.

假設兩個數組爲A, B長度分別爲m,n.分別是遞增順序。

可以採用的算法有很多:

首先想到的是類似MergeSort的方式,合併的同時找第K大元素,這個基本沒難度,複雜度O(m + n)。

不過此算法並不是最優,還有Log級別複雜度的算法,此算法其實很簡單,遠沒有很多網站的代碼那麼玄乎,以下一一道來:

首先明白幾個前提:

1.如果是求中位數,(m + n)是奇數還是偶數對結果是很有影響的,具體的如果(m + n)是奇數,中位數唯一,如果是偶數就有兩個中位數,怎麼取捨就看要求了。

2.如果找到的第k大數(中位數類似)是 X ,如果X排在A中的 第Ax位置,X排序在B中的Bx位置,那麼(Ax + Bx - 1) == k 是恆成立的。

明白了2中的前提後,我們就可以得到一個算法,在A數組中枚舉X,加入在A中是第Ax個,那麼可以反推B中第 (k + 1 - Ax)個以及相鄰元素和X的大小關係就可以得到一個Log級別複雜度的算法:

簡單點我們可以這麼想:

1)先假設第k大數在A中,我們首先從A中第(m/(m + n)) * (k - 1)個元素開始檢查其是否是第k個元素,假設其值爲A1,然後看B中第(k + 1 - (m/(m + n)) * (k - 1)個元素(B1)和A1是否相等,或者 大於B中第(k + 1 - (m/(m + n)) * (k - 1))個元素,小於B中第(k + 1 - (m/(m + n)) * (k - 1))+ 1個元素。滿足及可以知道A1即爲所求。如果兩個條件都不滿足,請看2.

2)如果兩個條件都不滿足,那麼需要判斷第k個元素是處於 A1的左邊還是右邊,這個就是典型的分治思想。具體的來說:

             if A1 > B1  那麼k可以排除肯定不在A[0, (m/(m + n)) * (k - 1)]以及B[(k + 1 - (m/(m + n)) * (k - 1))+ 1, n]中

             if A1< B1  那麼k可以排除肯定不在A[ (m/(m + n)) * (k - 1), m]以及B[0, (k + 1 - (m/(m + n)) * (k - 1))]中.

             注意下臨界條件(corner condition may not stastify, but the method is right)

第K個元素有可能在B中,同理可以假設在B中,然後再搜索一遍就可以查到。複雜度 log(m)+ log(n)

當然也可以兩個數組一起找,總體代碼如下:

複製代碼
 1     int kthsmallest(int *a,int m,int *b,int n,int k) {
 2         if (m == 0) {
 3             return b[k - 1];
 4         }
 5         if (n == 0) {
 6             return a[k - 1];
 7         }
 8         if (k == 1) {
 9             return (a[0] < b[0])?a[0]:b[0];
10         }
11         if (k == m + n) {
12             return (a[m - 1] > b[n - 1])?a[m - 1]:b[n - 1];
13         }
14         int i = ((double) m) / (m + n) * (k - 1);
15         int j = k - 1 - i;
16         if (j >= n) {
17             j = n - 1;
18             i = k - n;
19         }
20         if (((i == 0) || (a[i - 1] <= b[j])) && (b[j] <= a[i])) {
21             return b[j];
22         }
23         if (((j == 0) || (b[j - 1] <= a[i])) && (a[i] <= b[j])) {
24             return a[i];
25         }
26         if (a[i] <= b[j]) {
27             return kthsmallest(a + i + 1, m - i - 1, b, j, k - i - 1);
28         } else {
29             return kthsmallest(a, i, b + j + 1, n - j - 1, k - j - 1);
30         }
31 
32     }
複製代碼
發佈了87 篇原創文章 · 獲贊 28 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章