zoukankan      html  css  js  c++  java
  • 分治法求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 }
  • 相关阅读:
    优化 Markdown 在 Notepad++ 中的使用体验
    error C1128: 节数超过对象文件格式限制: 请使用 /bigobj 进行编译
    Git: 代码冲突常见解决方法
    fatal error c1001 编译器中发生内部错误 OpenMesh6.3
    error C2448 函数样式初始值设定项类似函数定义
    VS Code 配置Python
    15分钟掌握 Git
    notepad++快捷键
    【Python笔记】第4章 操作列表
    【MySQL】MySQL按中文排序
  • 原文地址:https://www.cnblogs.com/f91og/p/6022464.html
Copyright © 2011-2022 走看看