LeetCode 尋找兩個有序陣列的中位數

2021-09-25 18:28:39 字數 3455 閱讀 3001

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。

請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o(log(m + n))。

你可以假設 nums1 和 nums2 不會同時為空。

示例 1:

nums1 = [1, 3]

nums2 = [2]

則中位數是 2.0

示例 2:

nums1 = [1, 2]

nums2 = [3, 4]

則中位數是 (2 + 3)/2 = 2.5

分析:

m為陣列a元素數量

n為陣列b元素數量

通過上圖我們可以得知:

1.在合併後的大陣列中,中位數的作用就是把陣列分成元素數量相同的兩部分,這兩部分的元素是連續的,並且右側的元素大於等於或者左側的元素(也就是橙色元素大於或者等於綠色元素)

2.大陣列中的元素不是來自於陣列a就是來自於陣列b,也就是說,陣列a和陣列b肯定是由分割線兩側的元素混合構成的(先不考慮特殊情況),由於他們都是有序陣列,那麼陣列a和陣列b中肯定也存在兩條這樣的分割線i和j,我們只需要在a陣列和b陣列中找到確切的i分割線和j分割線的位置,就可以確定大陣列中分割線的位置,從而就可以確定中位數的位置

3.那麼怎麼尋找合適的i和j呢?

i和j滿足的要求:i+j=(n+m+1)/2   (+1是為了保證元素總數量無論是奇數還是偶數該公式都成立)

根據公式知道,i和j只要確定了乙個,另外乙個也就確定了,所以我們只需要在陣列a中尋找合適的i,那什麼樣的i才是合適的i呢?

合適的i和j必須要滿足以下要求:

1)a[i]>=b[j-1]

2)b[j]>=a[i-1]

也就是保證所有橙色元素都大於或者等於綠色元素,換句話說就是為了保證大陣列中右側元素都大於或者等於左側元素,只有這樣的i和j才是合適的,才可以根據i和j確定大陣列中位數的位置

那麼當i和j不合適時,我們應該怎麼調整呢?我們調整i,j也會隨著變化,所有我只對i進行調整就好

當a[i]當b[j]我們可以通過二分的方式來移動i

當找到合適的i和j後

如果總元素數量為奇數,那麼左側最大元素max(a[i-1],b[j-1])就是中位數

如果總元素數量為偶數,那麼左側最大元素和右側最小元素的平均值就是中位數

ps:右側最小元素=min(a[i],b[j])

需要處理幾種特殊情況:

1)如果b元素數量比a元素數量少的話,通過i得到的j值在陣列b中可能會越界

解決方案:如果陣列a的元素數量比陣列b的元素數量多,那麼交換a,b陣列的元素,也就是說,i是在陣列元素數量少的陣列上移動的,這樣通過i得到的j值在b陣列肯定不會越界

2)i等於0的情況

這種情況下,i-1會越界,那麼左側的最大元素為b[j-1]就好

3)j等於0的情況

這種情況下,j-1會越界,那麼左側的最大元素為a[i-1]就好

4)i等於m的情況

這種情況下,a[m]元素取不到,也越界了,那麼右側最小元素為b[j]就好

5)j等於n的情況

這種情況下,b[j]元素取不到,也越界了,那麼右側最小元素為a[i]就好

時間複雜度分析:對a陣列進行二分尋找合適的i,又因為a陣列是元素數量最少的陣列,所以該演算法的時間複雜度為:o(log (min(m,n)))

空間複雜度:o(1)

另外一篇也很不錯的博文:

code:

double findmediansortedarrays(vector& a, vector&b)

int low=0

;

int high=m;

int k=(m+n+1)/2

;

while(low<=high)//

二分a陣列

else

if(i>low&&a[i-1]>b[j])//

i太大,i需要左移

else

//找到了合格的i,j

else

if(j==0

)

else

if((m+n)%2==1)//

如果兩個陣列的元素數量為奇數,那麼左側的最大值就是中位數

return maxleft*1.0

;

intminright;

//特殊情況

if(i==m)

else

if(j==n)

else

return (maxleft+minright)/2.0;//

元素總數量為偶數,那麼中位數等於左側最大值和右側最小值的平均值

} }

return

0.0;

}

另外一種時間複雜度稍微差點的方法將求中位數轉化為求第k大數,當k=(m+n+1)/2時,為原問題的解,那麼怎麼求兩個陣列的第k大數呢?分別求出a陣列和b陣列的第k/2個數x和y,然後比較x,y

當x當x>y時,說明第k個數字於b陣列的第k/2個數的前半段

問題規模縮小了一般,然後遞迴處理就行了(特殊情況的細節沒有說明,這裡只講解一下大概思路,因為該方法時間複雜度較高,為o(log(m+n))

具體請參考:

leetcode尋找兩個有序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。示例 1 nums1 1,3 nums2 2 則中位數是 2.0 示例 2 nums1 1,2 ...

二 Leetcode演算法尋找兩個有序陣列的中位數

1 題目 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不會同時為空。nums1 1,3 nums2 2 則中位數是 2.0 nums1 1,2 nums2...

LeetCode 尋找兩個有序陣列的中位數

題目時間複雜度要求不高於o log m n m,n分別是兩個陣列的長度。對數級的時間複雜度就應該用二分查詢來做了。整體思路就是 先分別找到兩個陣列的中位數a,b,如果ab,說明整體中位數字於a的前半段或b的後半段。不斷這樣二分下去即可。其實,這道題可以轉換為尋找有序陣列中的第k個數,對應於中位數的話...