4. Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
分析
尋找兩個已排序序列的中位數,中位數就是一個序列中位置中間的那個數,當元素個數爲奇數時,中位數就是第n/2
個元素;當元素個數爲偶數時,中位數就是第n/2
個元素和第 n/2 + 1
個元素的平均值;
最直接的方法就是合併兩個有序序列,然後找到第k
大元素。這種方法的時間複雜度爲O(k).
另一種法就是利用二分法思想(排序後是序列都很有可能利用二分法思想)。我們可以考慮從k
入手,如果每次都可以刪除一個一定在第k大元素之前的元素,那麼需要進行k
次。但是如果一次刪除一半呢?優於兩個序列是有序的,我麼可以充分利用這部分信息。
假設A序列和B序列的元素個數都大於k/2
,比較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[K/2-1] < B[K/2-1]
,則A[0]
到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
或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]
源碼
方法1:合併排序然後遍歷
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
double ret = 0;
int total = nums1.size() + nums2.size();
int m = 0, n = 0, count = 0;
int k = total / 2;
int a = 0, b = 0, tmp = 0;
while(count <= k) {
if(m >= nums1.size()) {
tmp = nums2[n];
n++;
} else if(n >= nums2.size()) {
tmp = nums1[m];
m++;
} else if(nums1[m] <= nums2[n]) {
tmp = nums1[m];
m++;
} else {
tmp = nums2[n];
n++;
}
count++;
a = b;
b = tmp;
}
if(total % 2 == 0) {
return (a + b) / 2.0;
} else {
return b;
}
}
方法二:二分遞歸
double findKth(int a[], int m, int b[], int n, int k)
{
if (m > n) // 總是假設a數組比b數組短
return findKth(b, n, a, m, k);
if (m == 0) // 短數組a的元素個數爲0時直接返回長數組b中的第k大元素
return b[k - 1];
if (k == 1) // k=1時直接返回兩個數組中首元素中的較小值
return min(a[0], b[0]);
//將k拆成兩部分
int pa = min(k / 2, m), pb = k - pa;
if (a[pa - 1] < b[pb - 1]) //a[0]...a[pa-1]一定在第k大元素的前面,後面只需要考察a[pa]...
return findKth(a + pa, m - pa, b, n, k - pa);
else if (a[pa - 1] > b[pb - 1])//b[0]...b[pb-1]一定在第k大元素的前面,後面只需要考察b[pb]...
return findKth(a, m, b + pb, n - pb, k - pb);
else
return a[pa - 1];
}
double _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);
else // 元素個數爲偶數
return (findKth(A, m, B, n, total / 2)
+ findKth(A, m, B, n, total / 2 + 1)) / 2;
}
class Solution
{
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
return _findMedianSortedArrays(&nums1[0], nums1.size(), &nums2[0], nums2.size());
}
}