寻找两个有序数组的中位数(C++)

先来了解一下割:

我们通过切一刀,能够把有序数组分成左右两个部分,切的那一刀就称为割(cut),割的左右会有两个元素,分别是左边最大值和右边最小值。

我们定义:LMax = Max(LeftPart), RMin = Min(RightPart)。

       割可以割在两个数中间,也可以割在一个数上,如果割在一个数上,那么这个数既属于 左 边,也属于右边。

奇数组:[2 , 3 , 5] 对应的中位数为 3 ,假定割( cut )在3上, 我们可以把 3 分为 2 个:[2  (3/3)  5],因此:LMax = 3 , RMin = 3

偶数组:[1 4 7 9] 对应的中位数为 (4 + 7) /2 = 5.5 ,假定割( cut )在4和7之间:[1  (4/7)  9],因此:LMax = 4 ,RMin = 7.

割和第k个元素:

一个数组

对于一个有序数组A,如果在k的位置割(cut)一下(不是割( cut )在两数中间),那么LMax = RMin = A[k].

两个数组:

也就是我们题目的状态,我们要求两个数合并成一个有序数组,第k位的元素

我们设:

Ci 为第 i 个数组的割。

LMaxi为第i个数组割后的左元素。

RMini为第i个数组割后的右元素。

首先,LMaxi <= RMini 这是肯定的。

其次,如果我们让LMax1 <= RMin2 ,LMax2 <= RMin1 呢,那么两个数组的左半边全小于右半边,如果左边的元素个数相加刚好等于k,那么第k个元素就是Max(LMax1, LMax2)。

那么如果 LMax1 > RMin2 , 说明数组1的左边元素太大,我们把C1减小, C2= k - C1也就相应增大;LMax2 > RMin1同理,把C2减小, C1 = K -C2 也就相应的增大。

假设 K = 3

 对于

        [2  3   5]

        [1  4  7  9]

设 C1 = 1 ,那么 C2 = k - C1 =2 ,即:

        [2  /  3   5]

        [1  4  / 7  9]

这时, LMax1 =2 ,RMin1 = 3 ,LMax2 = 4 ,RMin2 = 7,从而有LMax2 > RMin1 ,依据前面的推论,我们要将C1增大,所以我们让 C1 = 2 ,如下:

        [2  3 /   5]

        [1  /4  7  9]        

这时, LMax1 =3 ,RMin1 = 5 ,LMax2 = 1 ,RMin2 = 4,满足LMax1 < RMin2 ,LMax2 < RMin1 ,所以第3个元素为 Max(LMax1 , LMax2) = 3。

两个数组的最大问题是,他们合并后,m+n总数可能为奇,也可能为偶,所以我们得想办法让m+n总是为偶数。

通过虚拟加入 “#” , 我们让m转换成2m + 1 ,n转换成2n+1,两数之和就变成2m+2n+2,为偶数。要注意的是 ,我们这里是虚拟加,其实根本没有这一步,通过下面的转换,我们可以保证虚拟加后每个元素跟原来的元素一一对应:

        [#  2 # 3 #  5  #]

        [# 1 # 4 # 7 # 9 #]。

这样虚拟加之后,每个位置可以通过/2得到原来元素的位置。

而对于割( cut )而言,如果割在 “ #  ” 上等于割在 2 个元素之间,割在数字上等于把数字划到2个部分,总是有以下成立:

        LMaxi = (Ci - 1) / 2 位置上的元素

        RMini = Ci /2位置上的元素.

剩下的事情就好办了,把 2 个数组看做一个虚拟的数组A,A有2m+ 2n + 2个元素,割在m+n+1处,所以我们只需要找到m+n+1位和m+n+2位元素即可。

左边:A[m+n+1] = Max(LMax1 , LMax2)

右边:A[m+n+2] = Min(RMin1 , RMin2)

==> Mid  = (A[m+n+1]+A[m+n+2])/2

最快的割( cut )是二分法, 有两个数组,我们对那个做二分呢?根据之前的分析,我们知道了,只要C1或C2确定,另一个也就确定了。这里为了效率,我们肯定要选长度较小的进行二分,有二分递归公式:

        LMax1 >RMin2 , 把C1减小,C2增大.  ->C1向左二分。

        LMax2 >RMin1,  把C2减小,C1增大。->C1向右二分。

如果C1或C2到头了怎么办?我们假定 n < m,可能有4种情况:

        C1 = 0 ——  数组1整体都在右边了,所以都比中值大,中值在数组2中,简单的说就是数组1割后的左边是空了,我们可以假定LMax1 = INT_MIN

        C1 =2n——  数组1整体都在左边了,所以都比中值小,中值在数组2中,简单的说就是数组1割后的右边是空了,我们可以假定RMin1 = INT_MAX

        C2 = 0 ——  数组2整体都在右边了,所以都比中值大,中值在数组1中,简单的说就是数组1割后的左边是空了,我们可以假定LMax2 = INT_MIN

        C2 = 2m ——  数组1整体都在左边了,所以都比中值小,中值在数组1中,简单的说就是数组1割后的右边是空了,我们可以假定RMin2 = INT_MAX

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值