二分法--求兩有序數組中位數


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


}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章