问题:设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 }
posted on 2016-11-02 17:52  f91og  阅读(5282)  评论(0编辑  收藏  举报