求多个有序数组的中位数

题目:求解多个有序数组的中位数

题目的意思是如果多个有序数组能在一起排序,则取位置为中间的数字,如果有奇数个数字则中位数只有一个;若为偶数个则有两个,一般取第一个,也称下中位。但不能把数组合在一起做插入或快速排序,因为数据可能是海量的。

该题目可能有很多种实现方法,而我们给出一种仅依赖中位数性质的算法。如果存在一个已经排好序的大数组(有序数列),则会发现几个性质:

  1. 对称性:中位数前面的数字与后面的数字一样多(在偶数元素情况下或相差1)
  2. 确定性:若某个数字前后的数字数量相同(或相差1)则为该数列的中位数
  3. 不变性:删除前N个元素与后N个元素后,中位数不变
  4. 关联性:从大数组中按顺序任意取走n-1组元素,与剩下的元素共构成n个子列,每个子列存在中位数:m1,m1…mn,min,max分别为其中最小者与最大者,则原数列的中位数m满足:min<=m<=max
    该性质可通过反证法获得

根据上述性质构造下面基于3分查找的算法:

  1. 输入多个有序数组查找其中位数m
  2. 计算个数组的中位数,并计算其最小者min与最大者max,则m必满足min<=m<=max
  3. 计算min之前所有的数字lTripCount(在所有数组)及max之后所有的数字rTripCount,如果二者相同,则min与max都为中位数,递归结束
  4. 计算所有数组中属于区间[min,max]的中位数(小于min或大于max的全被舍弃)m1,如果m1满足lTripCount==rTripCount,则为中位数,递归结束
  5. 如果lTripCount<rTripCount,则中位数m一定属于区间[min,m1]
  6. 如果lTripCount>rTripCount,则中位数m一定属于区间(m1,max]
  7. 递归上述过程
  8. 若某个递归后发现各数组剩余的数据小于某个阀值,则考虑一起计算,从而终止递归

该算法的主要思想是利用子数组的中位数逼近全数组的中位数,具体过程如下:  要排序的全数组:
《求多个有序数组的中位数》

其中10便是要求解的中位数,数组A被划分为下面三个子数组:
《求多个有序数组的中位数》

计算步骤:

  1. 分别计算A1,A2,A3的中位数,分别为7,9,11
  2. 根据关联性,则要寻找的中位数(10)必定满足7<=m<=11
  3. 从A1,A2,A3中去除小于7,大于11的数,此时各子数组的数据情况如下:
    《求多个有序数组的中位数》
  4. 继续计算各子数组的中位数,可的A1:10,A2:9,A3:11,因为此时各数组只剩一个元素,故根据假设可在一起计算其中位数10
  5. 以10为中心计算lTripCount、rTripCount,经过计算二者相同,根据确定性可断定10为最终的中位数;如果lTreipCount与rTripCount不同,则可推导中位数会落在哪个区间(参考上面的算法描述),从而递归上面的过程

因为每次都根据最小中位数与最大中位数过滤,故每次计算可大约砍掉2/3的数据,算法大约以3
n的速度收敛。 上述算法可能会产生一个无法收敛的特殊场景:如果某个计算过程出现最小中位数为当前有效数据的最小值,而最大中位数为最大值,则无法过滤掉更多的数据,解决该问题的办法是根据不变性,同时删除最小中位数与最大中位数。

点赞