两个有序数列的中位数

两个有序数列的中位数

力扣第四题,Median of Two Sorted Substring.

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

思路

求中位数的过程可以看作分组和取中心两步。

分组

分组的条件是:

  1. 左侧组最大值小于等于右侧组最小值(左侧组每个元素都比右侧组中的小)

  2. 两组元素数量相等

条件2在元素总数是奇数时不可能满足。我们在这里需要做出抉择,多出的元素分给左侧组还是右侧组1

取中心

中心的位置有两种情况:

  1. 两组最值的平均值(元素数是偶数)
  2. 某组的最值(元素数是奇数)

下面说明如何实现。

分组

这里选择将多出的元素分到左侧组:

def partion(arr1, arr2):
    
    def is_safe_ref(arr, index):
        return 0 <= index < len(arr)
    
    def improve(imin, imax):
        i = (imin + imax) // 2
        j = (m + n + 1) // 2 - i    # len(left) >= len(right)
        
        if is_safe_ref(arr1, i - 1) and is_safe_ref(arr2, j) and arr1[i - 1] > arr2[j]:
            return improve(imin, i - 1)
        elif is_safe_ref(arr1, i) and is_safe_ref(arr2, j - 1) and arr1[i] < arr2[j - 1]:
            return improve(i + 1, imax)
        else:
            return i, j
    
    m, n = len(arr1), len(arr2)
    return improve(0, m)

由于不能合并数组,这里用i, j标记左右的分界线。

取中心

def medium(arr1, arr2, i, j):
    """(max_of_left + min_of_right) // 2"""
    
    m, n = len(arr1), len(arr2)
    
    if i == 0:
        max_of_left = arr2[j - 1]
    elif j == 0:
        max_of_left = arr1[i - 1]
    else:
        max_of_left = max(arr1[i - 1], arr2[j - 1])
    
    if is_even(m + n):
        
        if i == m:
            min_of_right = arr2[j]
        elif j == n:
            min_of_right = arr1[i]
        else:
            min_of_right = min(arr1[i], arr2[j])
            
        return (max_of_left + min_of_right) / 2
    else:
        return float(max_of_left)

多余元素划分到左侧组,两数组又不同时为空,所以无论总元素数是奇是偶,左侧组至少有一个元素。总元素数是偶数时,右侧组至少有一个元素。



  1. 如果允许既不属于左侧组又不属于右侧组的元素存在,就必须考虑“第三分组”的元素个数,以及“第三分组”何时存在等等问题,引入更多的复杂性。 ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值