1.分析问题:
这里有两点条件,长度相等,任意元素大于。所以列出下面的模型,为了后面便于思考
left_part | right_part lee
A[0], A[1], …, A[i-1] | A[i], A[i+1], …, A[m-1]
B[0], B[1], …, B[j-1] | B[j], B[j+1], …, B[n-1]
其中
m:A数组长度
n:B数组长度
i:A数组的分割点,一共有m+1个分割点,i=0,1,2…m
j:B数组的分割点,一共有n+1个分割点,j=0,1,2…n
2.找出判断条件:
根据中位数的性质,得出判断条件为:
(1) len(left_part) == len(right_part)
(2) max(left_part) <= min(right_part)
首先设置n>=m,原因如下:
即设置数组A为长度较小的数组。如果数组A的长度大于数组B的长度,A的分割点无法到取到靠后的位置,因为可能会使leftA的长度大于rightA+lenB的长度。这样i就可以任意取,i , j 结果都为正,我们只要考虑 i的范围即可,有序数组的查找显然后面可以使用二分法。
继续推导判断条件,有两种情况:
<1> 当m+n为偶数时,中位数是中间两数之和,若想找到正确的i,应该有:
(1) i + j == m - i + n - j
(2) B[j-1] <= A[i] and A[i-1] <= B[j]
最后的结果为 (max(A[i-1], B[j-1]) + min(A[i], B[j]))/2
<2> 当m+n为奇数时,中位数是中间的一个数,把中间的数归到左半部分,则有:
(1) i + j == m - i + n - j + 1
(2) B[j-1] <= A[i] and A[i-1] <= B[j]
这时最后的结果为 max(A[i-1], B[j-1])
我们之前设置过i是可以任意取值的,于是有j=(m+n)/2-i,并且其中j > 0。
当m+n为偶数时,(m+n)/2==(m+n+1)/2,所以以上两种情况的判断条件可以合并,但两种情况的中位数结果是不同的,于是得到最终判断条件为:
(1) i = 0 ~ m, j = (m + n + 1)/2 - i
(2) B[j-1] <= A[i] and A[i-1] <= B[j]
3.确定循环过程:
根据上面的特点,可以对i使用二分法查找,并且根据之前对奇偶情况结果的讨论,需要保存left_part_max和right_part_min。
设置imin=0,imax=m,i=(imin+imax)/2,则对于一个给定的i,有如下几种情况:
搜索过程:
<1> B[j-1] > A[i] && i < m , 需要增加i,令imin=i+1
<2> A[i-1] > B[j] && i > 0 , 需要减小i,令imax=i-1
备注:(i小于m时,因为m<=n,j若等于0,右半部分元素会过多,所以j一定大于0)
(i大于0时,因为m<=n,j若等于n,左半部分元素会过多,所以j一定小于n)
之后判断各边界位置的情况来得到leftmax和righmin
代码如下:
class Solution {
public:
double findMedianSortedArrays(vector& nums1, vector& nums2) {
int m=nums1.size();
int n=nums2.size();
if(m>n)
{
return findMedianSortedArrays(nums2,nums1);
}
int imin=0;
int imax=m;
int amount=(m+n+1)/2;
while(imin<=imax)
{
int i=(imin+imax)/2;
int j=amount-i;
if(i<m&&nums1[i]<nums2[j-1])
{
imin=i+1;
}
else if(i>0&&nums2[j]<nums1[i-1])
{
imax=i-1;
}
else
{
int leftmax;
if(i==0)
{
leftmax=nums2[j-1];
}
else if(j==0)
{
leftmax=nums1[i-1];
}
else leftmax=max(nums2[j-1],nums1[i-1]);
if((n+m)%2==1)
{
return leftmax;
}
int rightmin;
if(i==m)
{
rightmin=nums2[j];
}
else if(j==n)
{
rightmin=nums1[i];
}
else rightmin=min(nums1[i],nums2[j]);
return (rightmin+leftmax)/2.0;
}
}
return 0;
}
};