描述
两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n))。
样例
给出数组A = [1,2,3,4,5,6] B = [2,3,4,5],中位数3.5
给出数组A = [1,2,3] B = [4,5],中位数 3
挑战
时间复杂度为O(log n)
思路
本质上是二分查找, 只不过条件比较奇葩。除了思路之外难点还在于特殊情况非常多。不知道大家是怎么在一开始处理这些特殊情况的,我的处理有点杂乱,是case-oriented。
class Solution {
public:
/*
* @param A: An integer array
* @param B: An integer array
* @return: a double whose format is *.5 or *.0
*/
int min(int a, int b)
{
if(a<b) return a;
else return b;
}
int max(int a, int b)
{
if(a<b) return b;
else return a;
}
double binarySearch(int low, int high, vector<int> A, vector<int> B, int nm2, bool even)
{
if(low >= high)
{
if(low != A.size()-1)
{
if(even)
{
return (double(max(A[low], B[nm2-low]))+double(min(A[low+1],B[nm2-low+1])))/2;
}
else
{
return max(A[low], B[nm2-low+1]);
}
}
else
{
if(even)
{
return (double(max(A[low], B[nm2-low]))+B[nm2-low+1])/2;
}
else
{
return max(A[low], B[nm2-low+1]);
}
}
}
int mid = (low+high)/2;
if(even)
{
if(A[mid] > B[nm2-mid+1])
{
high = mid-1;
if(mid == 0)
{
int id = B.size() - (nm2+2 - A.size()) - 1;
if(id == B.size()-1)
{
return (double(B[id])+double(A[0]))/2;
}
else
{
return (double(B[id])+double(B[id+1]))/2;
}
return B[id];
}
return binarySearch(low, high, A,B, nm2,even);
}
else if(B[nm2-mid] > A[mid+1])
{
low = mid+1;
return binarySearch(low, high, A,B, nm2,even);
}
else
{
return (double(max(A[mid], B[nm2-mid]))+double(min(A[mid+1],B[nm2-mid+1])))/2;
}
}
else
{
if(A[mid] > B[nm2-mid+2])
{
high = mid-1;
if(mid == 0)
{
int id = B.size() - (nm2+2 - A.size()) - 1;
return B[id];
}
return binarySearch(low, high, A,B, nm2,even);
}
else if(B[nm2-mid+1] > A[mid+1])
{
low = mid+1;
return binarySearch(low, high, A,B, nm2,even);
}
else
{
return max(A[mid], B[nm2-mid+1]);
}
}
}
double findMedianSortedArrays(vector<int> &A, vector<int> &B) {
// write your code here
/*
A1,A2,A3..Ai | Ai+1, Ai+2...An
B1,B2,B3..Bj | Bj+1, Bj+2...Bm
Ai < Bj+1 && Bj < Ai+1
if even=>
i+j = n+m-i-j => j= (n+m)/2 - i
if odd=>
i+j+1 = n+m-i-j-1 => j= (n+m)/2 - i-1
*/
int i=0, j=0;
int n=A.size(), m=B.size();
bool even=false;
if((n+m) %2 == 0)
{
even=true;
}
if(A.size() == 0)
{
if(B.size() == 0)
{
// error
}
else
{
if(even)
{
return (double(B[B.size()/2])+double(B[B.size()/2-1]))/2;
}
else
{
return B[B.size()/2];
}
}
}
else if(B.size() == 0)
{
if(A.size() == 0)
{
// error
}
else
{
if(even)
{
return (double(A[A.size()/2])+double(A[A.size()/2-1]))/2;
}
else
{
return A[A.size()/2];
}
}
}
int lowi = 0;
int highi = A.size()-1;
int nm2 = (n+m)/2-2;
double ans;
if(n<m)
{
ans = binarySearch(lowi, highi, A, B, nm2, even);
}
else
{
ans = binarySearch(lowi, highi, B, A, nm2, even);
}
return ans;
}
};