here are two sorted arrays A and B 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)).
求两个已排序数组的中位数问题,数组长度分别为m,n,时间复杂度要求O(log(m+n))
中位数定义:对一个已排序数组a,设长度为l,若l为奇数,中位数为a[l/2],即中间的那个数;若l为偶数,中位数为(a[l/2-1]+a[l/2])/2,即中间的两数的平均值
解法见另一篇转载:http://blog.csdn.net/maverick1990/article/details/21406739
几个需要注意的细节:
1、注意处理m或n长度为0的情况
2、设a当前遍历区间为[al,ar],那么中点为am = (al+ar)/2,设要找第pos位置的数(pos=(m+n)/2),那么把A[am]放到数组B中的对应位置ainb=pos-am,即数组A中A[am]前面有am个数,那么如果A[am]是中位数,在数组B中要有ainb=pos-am个数小于A[am],A[am]要放在B[ainb-1]和B[ainb]两数之间。此时要注意:
(1)ainb是否合法,即满足0<=ainb且ainb-1<n,保证ainb-1,ainb有一个在B数组内。
若ainb<0,证明A[am]前面的am个数已经大于(m+n)/2了,直接将更新ar为am-1;ainb-1>=n的情况以此类推
(2)更新坐标时,要置为ar=am-1或al=am+1,注意边界,防止死循环,并且最后判断new_al是否大于new_ar,若大于,都重新置为原来的al。原因如下:
分析ar-al=1和0的两种边界情况,ar-al=1时,am=al,更新后的情况为,new_al = al, new_ar = al-1 或 new_al = ar, new_ar = ar,对于前一种情况,将new_al和new_ar都置为al为合理;ar=al时,更新后的情况为,new_al = al, new_ar = al-1 或 new_al = ar+1, new_ar = ar,对于这两种情况,将new_al和new_ar都置为al为合理
本题考察重点就是这些细节,我在这上面费了不少时间,面试时候一次写对还是不太容易的。
代码:
#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
class Solution {
private:
int pm,pn;
public:
int findPos(int A[],int al,int ar,int B[],int bl,int br,int pos)
{
int am = (al+ar)/2;
int bm = (bl+br)/2;
int ainb = pos-am;
int bina = pos-bm;
int nal=al,nar=ar,nbl=bl,nbr=br;
if(ainb<0)
nar = am-1;
else if(ainb-1>=pn)
nal = am+1;
else if(ainb<pn && A[am]>B[ainb])
nar = am-1;
else if(ainb>0 && A[am]<B[ainb-1])
nal = am+1;
else
return A[am];
if(bina<0)
nbr = bm-1;
else if(bina-1>=pm)
nbl = bm+1;
else if(bina<=ar && B[bm]>A[bina])
nbr = bm-1;
else if(bina>0 && B[bm]<A[bina-1])
nbl = bm+1;
else
return B[bm];
if(nal>nar) nal=nar=al;
if(nbl>nbr) nbl=nbr=bl;
return findPos(A,nal,nar,B,nbl,nbr,pos);
}
double findMedianSortedArrays(int A[], int m, int B[], int n)
{
//printf("%d %d\n",m,n);
//printf("%d %d %d %d\n",A[0],A[m-1],B[0],B[n-1]);
pm = m;
pn = n;
double ans;
if(m==0)
{
ans = B[n/2];
if(n%2==0) ans = (B[n/2-1]+ans)/2.0;
}
else if(n==0)
{
ans = A[m/2];
if(m%2==0) ans = (A[m/2-1]+ans)/2.0;
}
else
{
int al = 0;
int ar = m-1;
int bl = 0;
int br = n-1;
int mid = (m+n)/2;
ans = findPos(A,al,ar,B,bl,br,mid);
if((m+n)%2==0)
ans = (findPos(A,al,ar,B,bl,br,mid-1)+ans)/2.0;
}
return ans;
}
};
int main()
{
Solution t;
int a[] = {1,2,3,4,5};
int b[] = {2,4,7};
cout<<t.findMedianSortedArrays(a,sizeof(a)/sizeof(int),b,sizeof(b)/sizeof(int))<<endl;
}