求两个有序数组的中位数
设用
i
i
分割数组定义从在数组的第 个元素的左边将数组分割成两个子数组。如
i=2
i
=
2
时,
[1,2,3,4]→[1,2]和[3,4]
[
1
,
2
,
3
,
4
]
→
[
1
,
2
]
和
[
3
,
4
]
。
那么为了找两个有序数组的中位数,假设两个数组长度之和为偶数,我们用
i
i
分割第一个数组, 分割第二个数组,那么
i+j=len(arr1)+len(arr2)2
i
+
j
=
l
e
n
(
a
r
r
1
)
+
l
e
n
(
a
r
r
2
)
2
且设
Li
L
i
为第
i
i
个数组的割的左边的数,如果不存在则为无穷小, 为第
i
i
个数组的割右边的数,如果不存在则为无穷大,那么 ,
L1≤R1
L
1
≤
R
1
满足。因为当
i
i
确定了那么 也确定了。因此可以用数组长度最短的那个数组进行二分,如果
L1>R2
L
1
>
R
2
说明
i
i
还需左移,如果 ,说明
i
i
<script type="math/tex" id="MathJax-Element-2143">i</script> 还需右移。
为了保证数组长度之和是偶数,可以在数组中添加 #
。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size(), m = nums2.size();
if(n>m) return findMedianSortedArrays(nums2, nums1);// nums1最短
int total=n+m;
int l=0,r=2*n,L1,R1,L2,R2;
//将原数组中加'#',让两个数组的长度都为偶数。这样就避免了两个数组长度加起来是奇数的问题。
//如 [1 2 3 4] 变为 [# 1 # 2 # 3 # 4]
while(l<=r)
{
int c1=(l+r)/2;
int c2=n+m-c1;
//割到左边沿,值为INT_MIN,割到右边沿,值为INT_MAX
L1=(c1==0)?INT_MIN:nums1[(c1-1)/2];
R1=(c1==2*n)?INT_MAX:nums1[c1/2];
L2=(c2==0)?INT_MIN:nums2[(c2-1)/2];
R2=(c2==2*m)?INT_MAX:nums2[c2/2];
if(L1>R2) r=c1-1;
else if(L2>R1) l=c1+1;
else break;
}
return (max(L1,L2)+min(R1,R2))/2.0;
}
};