思路一:
1.记数组A长度为m,数组B长度为n,求中位数分两种情况,一种是元素个数为奇数,中位数为两个数组合并之后第(m+n+1)/2个元素,另一种是元素个数为偶数的情况,中位数为两个数组合并之后第(m+n+1)/2、(m+n+1)/2+1个元素。
2.所以问题转化成求两个有序数组合并后的第k或者k+1个元素。
3.注意到两个数组都是有序数组这个条件,我们需要充分利用有序这个条件,以及结合我们求解的最终问题是求解一个中位数,引导我们求解往二分的方向去思考。
4.取A[
⌊
k
/
2
⌋
\lfloor k/2\rfloor
⌊k/2⌋-1]和B[
⌊
k
/
2
⌋
\lfloor k/2\rfloor
⌊k/2⌋-1]两个元素,比较其大小。
结果有三种情况
{
1.
A
[
⌊
k
/
2
⌋
−
1
]
<
B
[
⌊
k
/
2
⌋
−
1
]
则
证
明
最
多
有
⌊
k
/
2
⌋
+
⌊
k
/
2
⌋
−
2
个
元
素
是
于
A
[
⌊
k
/
2
⌋
−
1
]
的
,
加
上
A
[
⌊
k
/
2
⌋
−
1
]
,
则
说
明
A
[
0
,
⌊
k
/
2
⌋
−
1
]
的
所
有
元
素
不
可
能
是
合
并
后
的
数
组
的
第
k
个
元
素
,
故
舍
弃
掉
这
部
分
元
素
,
总
共
⌊
k
/
2
⌋
个
,
要
求
解
的
数
组
规
模
开
始
减
小
,
我
们
只
需
要
求
解
剩
余
数
组
中
第
k
−
⌊
k
/
2
⌋
个
元
素
即
可
。
2.
A
[
⌊
k
/
2
⌋
−
1
]
>
B
[
⌊
k
/
2
⌋
−
1
]
情
况
类
似
,
只
需
要
去
掉
B
[
0
,
⌊
k
/
2
⌋
−
1
]
,
然
后
更
新
k
即
可
3.
A
[
⌊
k
/
2
⌋
−
1
]
=
B
[
⌊
k
/
2
⌋
−
1
]
,
可
以
归
入
小
于
的
情
况
。
\begin{cases} 1.A[\lfloor k/2\rfloor-1]<B[\lfloor k/2\rfloor-1]\\ 则证明最多有\lfloor k/2\rfloor+\lfloor k/2\rfloor-2个元素是于A[\lfloor k/2\rfloor-1]的,加上A[\lfloor k/2\rfloor-1],则说明\\A[0,\lfloor k/2\rfloor-1]的所有元素不可能是合并后的数组的第k个元素,故舍弃掉这部分元素,\\总共\lfloor k/2\rfloor个,要求解的数组规模开始减小,我们只需要求解剩余数组中第k-\lfloor k/2\rfloor个\\元素即可。\\ 2.A[\lfloor k/2\rfloor-1]>B[\lfloor k/2\rfloor-1] \\情况类似,只需要去掉B[0,\lfloor k/2\rfloor-1],然后更新k即可\\ 3.A[\lfloor k/2\rfloor-1]=B[\lfloor k/2\rfloor-1], \\可以归入小于的情况。\\ \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧1.A[⌊k/2⌋−1]<B[⌊k/2⌋−1]则证明最多有⌊k/2⌋+⌊k/2⌋−2个元素是于A[⌊k/2⌋−1]的,加上A[⌊k/2⌋−1],则说明A[0,⌊k/2⌋−1]的所有元素不可能是合并后的数组的第k个元素,故舍弃掉这部分元素,总共⌊k/2⌋个,要求解的数组规模开始减小,我们只需要求解剩余数组中第k−⌊k/2⌋个元素即可。2.A[⌊k/2⌋−1]>B[⌊k/2⌋−1]情况类似,只需要去掉B[0,⌊k/2⌋−1],然后更新k即可3.A[⌊k/2⌋−1]=B[⌊k/2⌋−1],可以归入小于的情况。
5.特殊情况
如果
A
[
⌊
k
/
2
⌋
−
1
]
或
者
B
[
⌊
k
/
2
⌋
−
1
]
A[\lfloor k/2\rfloor-1]或者B[\lfloor k/2\rfloor-1]
A[⌊k/2⌋−1]或者B[⌊k/2⌋−1]越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 kk 的值,而不能直接将k减去
⌊
k
/
2
⌋
\lfloor k/2\rfloor
⌊k/2⌋。
如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 kk 小的元素。
如果 k==1,我们只要返回两个数组首元素的最小值即可。
代码:
class Solution {
public:
double getKnums(vector<int>& nums1, vector<int>& nums2,int k)
{
int m=nums1.size();
int n=nums2.size();
int b1=0;
int b2=0;
int h1=0;
int h2=0;
while(1)
{
if(b1>=m)
return nums2[b2+k-1];
else if(b2>=n)
return nums1[b1+k-1];
else if(k==1)
return nums2[b2]<nums1[b1]?nums2[b2]:nums1[b1];
h1=min(b1+k/2-1,m-1);
h2=min(b2+k/2-1,n-1);
if(nums1[h1]<=nums2[h2])
{
k-=h1-b1+1;
b1=h1+1;
}
else
{
k-=h2-b2+1;
b2=h2+1;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size();
int n=nums2.size();
if((m+n)%2)
return getKnums(nums1,nums2,(m+n+1)/2);
else
return (getKnums(nums1,nums2,(m+n)/2)+getKnums(nums1,nums2,(m+n)/2+1))/2;
}
};
思路二
利用归并排序思想求第k个元素,k为(m+n)/2或者(m+n)/2+1
代码
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size();
int n=nums2.size();
int c=(m+n)/2+1;
int c1=0;
int c2=0;
int p1=0;
int p2=0;
while(p2+p1<c)
{
if(p1<m&&p2<n)
{
c1=c2;
c2=nums1[p1]<nums2[p2]?nums1[p1++]:nums2[p2++];
}
if(p1<m&&p2>=n&&p2+p1<c)
{
c1=c2;
c2=nums1[p1];
p1++;
}
if(p2<n&&p1>=m&&p2+p1<c)
{
c1=c2;
c2=nums2[p2];
p2++;
}
}
if((m+n)%2)
return 1.0*c2;
else
return (c1+c2)/2.0;
}
};