有兩個已排好序的數組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);
}
}