給定兩個大小為 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)另外一種時間複雜度稍微差點的方法將求中位數轉化為求第k大數,當k=(m+n+1)/2時,為原問題的解,那麼怎麼求兩個陣列的第k大數呢?分別求出a陣列和b陣列的第k/2個數x和y,然後比較x,yint 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;
}
當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個數,對應於中位數的話...