题目
There 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)).
注意时间复杂度要求。线性时间算法是比较容易的,利用merge的思想即可。即使数组没有排序,也可用partition达到线性时间的选择,但是这里要求O(log (m+n))。
主要思想:
用O(log (m+n))选择两个数组中第k个数,先假设两个数组都足够长,递归操作如下。
1、比较A[k/2-1]、B[k/2-1]
如果A[k/2-1]<B[k/2-1],那么[A[0],A[k/2-1]必然都小于第k个数,去除这部分,k=k-k/2;
如果A[k/2-1]>B[k/2-1],那么[B[0],B[k/2-1]必然都小于第k个数,去除这部分,k=k-k/2;
如果相等,任意进行上述两种操作(其实A[k/2-1]、B[k/2-1]就是要选的数,如果A、B长度不足则需要如此操作)
2、如果A,B任意一个为空,取另一个的第k个
3、如果k=1,则取min(A[0],B[0])
实际情况下,1中如A,B长度不足,则取最后的那个数的编号代替k/2-1。
代码:递归
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
if((m+n)%2==1)
return findKth(A,m,B,n,(m+n)/2+1);
else
return (findKth(A,m,B,n,(m+n)/2)+findKth(A,m,B,n,(m+n)/2+1))/2.0;
}
double findKth(int A[],int m,int B[],int n,int k)
{
if(m==0)
return B[k-1];
if(n==0)
return A[k-1];
if(k==1)
return min(A[0],B[0]);
int pa=min(k/2,m);
int pb=min(k/2,n);
if(A[pa-1]<=B[pb-1])
return findKth(A+pa,m-pa,B,n,k-pa);
else
return findKth(A,m,B+pb,n-pb,k-pb);
}
};
代码:迭代,实测速度可以快30%(多次提交发现时间是不同的,相差还不小,速度提升没那么多,不过还是快15%左右……)
对于题目取中值的情况,如果返回abegin,bbegin,k,理论上可以再提高50%的速度。
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
if((m+n)%2==1)
return findKth(A,m,B,n,(m+n)/2+1);
else
return (findKth(A,m,B,n,(m+n)/2)+findKth(A,m,B,n,(m+n)/2+1))/2.0;
}
double findKth(int A[],int m,int B[],int n,int k)
{
int abegin=0,aend=m,bbegin=0,bend=n;
int pa,pb;
while(abegin<aend&&bbegin<bend&&k>1)
{
pa=min(abegin+k/2,aend);
pb=min(bbegin+k/2,bend);
if(A[pa-1]<=B[pb-1])
{
k-=pa-abegin;
abegin=pa;
}
else
{
k-=pb-bbegin;
bbegin=pb;
}
}
if(abegin>=aend)
return B[bbegin+k-1];
else if(bbegin>=bend)
return A[abegin+k-1];
else
return min(A[abegin],B[bbegin]);
}
};