有两个已排好序的数组A和B,长度均为n,找出这两个数组合并后的中间元素,要求时间代价为O(logn)。
先说说思路吧:
如果采用分别遍历,时间复杂度肯定超过logn,这里采用二分法,充分利用两个数组都是有序的,记midA,midB为数组A,B的中间数,如果A[midA]==B[midB],则A[midA](B[midB])就是我们要找的中位数了,而如果A[midA]>B[midB]那么,则中间数在midA的左边,midB的右边,这样我们就能缩小范围了,同样的A[midA]<B[midB]的话,中间数在midA的右边,midB的左边。
注意的是,我们的理念是丢的数要对称,所以要考虑剩下的数长度是奇数还是偶数了,对于奇数,中间数是唯一的,而对于偶数中间数有两个,我们这里取前一个,所以当丢弃的时候就要判断,如果一个丢弃左边,一个右边,这里会多丢一个数,而使结果不准确。
public class GetNumMiddle {int temp;
public double getMiddle(int A[],int l1,int r1,int B[],int l2,int r2){
int midA,midB;
midA=(l1+r1)/2;
midB=(l2+r2)/2;
if(l1==r1&&l2==r2)
return (double)(A[l1]+B[l2])/2;
if(r1-l1==1 && r2-l2==1){
if(A[midA]>B[midB]){
return (double)(A[midA]+B[midB])/2;
}else {
System.out.println("aaa");
}
}
if(A[midA]==B[midB]){
return A[midA];
}else if(A[midA]>B[midB]){
if(r1-midA>midB-l1) temp=r1-midA;
else temp=midB-l1;
return getMiddle(A,l1,r1-temp,B,l2+temp,r2);
}else {
if(midA-l1>r2-midB) temp=midA-l1;
else temp=r2-midB;
return getMiddle(A, l1+temp,r1, B,l2,r2-temp); //这里加这个判断主要是为了A,B丢的数相同。
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int A[]={1,2,3,4,5,6,7},B[]={2,4,6,8,9,10,12};
GetNumMiddle getNumMiddle=new GetNumMiddle();
double result= getNumMiddle.getMiddle(A,0, A.length-1,B,0,B.length-1);
System.out.println("结果是:"+result);
}
}