分治法求2n個數的中位數


問題:設X[0:n-1]和Y[0:n-1]為兩個數組,每個數組中含有n個已排好序的數。試設計一個O(logn)時間的分治算法,找出XY的2n個數的中位數

思想:

對於數組X[0:n-1]和Y[0:n-1]先分別找出X和Y的中位數xa和yb。求中位數的算法是這樣的,若n是奇數,即數組X和Y中各有奇數個數字,因為X和Y已經排好序了,所以去數組下標為(n-1)/2處的數即為中位數。若n是偶數,則取(n-1)/2向下取整和向上取整這兩個位置的數的平均值作為中位數。

兩者進行比較,

(1)若xa=yb則xa或者xb即為整個2n個數中的中位數,算法結束。因為:若每個數組中數字的個數是偶數個,則X中小於中位數的有n/2個,大於中位數的有n/2個,同理Y也是如此,所以在整個2n數組中比xa=yb小的共有n個數,比n大的共有n個數,即為中位數。若每個數組中數字的個數是奇數,則X中小於xa的有(n-1)/2個,大於xa的也有(n-1)/2個,同理Y中也是如此,所以對於xa或者是yb則整個2n數組中小於和大於他們的數分別為(n-1)個,取這兩個數的平均值(xa+yb)/2=xa=yb即為中位數.

(2) 若xa>yb,則說明整個2n個數的的中位數一定在X數組的前一半和Y數組的后一半中,因為:若中位數在X數組的中位數之后,則比它小的數共有X數組中大於n/2個數以及Y數組中大於n/2個數總計超過了n個數,不符合中位數的定義。若中位數是在Y數組的前一半之中,則比它大的數字共有Y中包括中位數在內的后半部數加上X數組包括中位數在內的后半部,這樣也超過了n個數,不符合中位數的定義。

(3) 若xa<yb,則同上理由,整個2n的數的中位數應該在X數組的后一半和Y數組的前一半中。

確定中位數所在的數組范圍后,遞歸調用求中位數算法對這個范圍的數組求中位數重復上述過程,直至:

         1.出現xa=yb情況,找到了中位數算法結束。

    2.數組分割至左右兩部數組只有一個數字的情況,求其平均值即為中位數

 

代碼:

 1 /*
 2 思路:求兩有序數組x和y的第k個數,思路如下:
 3 若k為1,則返回兩數組的最小值
 4 取x的第i個數x0,取y的第(k-i)個數y0
 5 若x0=y0,則x0即為所求
 6 若x0<y0,則丟棄x的前i個數,k=k-i,遞歸
 7 若x0>y0,則丟棄y的前(k-i)個數,k=i,遞歸
 8 */
 9 import java.util.Scanner;
10 import java.util.List;
11 import java.util.ArrayList;
12 
13 public class Solution{
14    
16     public int findOneSideMedian(int a[]){
17         int mid;
18         int length=a.length;
19         //if(a[])數組長度a.length
20         if((length&0x01)==0){//判斷子數組的長度是奇數還是偶數
21             mid=(a[length/2]+a[length/2-1])/2;
22         }else{
23             mid=a[length/2];
24         }
25         return mid;
26     }
27     
28     public double findMedian(int x[],int y[] int n){
29         if(n==0){
30             break;
31         }
32         int mid_x=findOneSideMedian(x);
33         int mid_y=findOneSideMedian(y);
34         if(n==1){
35             return (mid_x+mid_y)/2;
36         }
37         if(mid_x==mid_y){
38             return mid_x;
39         }else if(mid_x>mid_y){
40             int[] x2=Arrays.copyOfRange(x,0,n/2);
41             int[] y2=Arrays.copyOfRange(y,Math.ceil(n/2),n);
42             n=n/2;
43             findMedian(x2,y2,n);
44         }else if(mid_x<mid_y){
45             int[] x2=Arrays.copyOfRange(x,Math.ceil(n/2),n);
46             int[] y2=Arrays.copyOfRange(y,0,n/2);
47             n=n/2;
48             findMedian(x2,y2,n);
49         }
50     }
51 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM