寻找两个正序数组的中位数

本文内容摘录于leetcode,图解请查看以下网址:

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/

题目

寻找两个正序数组的中位数

解答

# LeetCode 二分法 官方解答整理
# 若数组的长度 n 为奇数,则中位数就是下标为 n/2 的值,若 n 为偶数,那么中位数就是下标为 n/2 和 (n/2+1) 的和的平均值
# 所以问题可以转化为,对于一个给定的数 k ,如何快速有效的实现找到第 k 个小的数,即拥有 k-1 个小于等于自己的数
def get_median(a,b):
    if (len(a)+len(b))%2 == 1 :
        return (find_k(a,b,(int)((len(a)+len(b))/2 + 1)))
    else:
        return (find_k(a,b,(int)((len(a)+len(b))/2)) + find_k(a, b, (int)((len(a)+len(b))/ 2 + 1)))/2
        
# 我们可以使用 (k/2-1) 作为关键性下标,去寻找数组中第 k 小的数
# - A 中存在 k/2-1 个比 A[k/2-1] 小的数,B 中存在 k/2-1 个比 B[k/2-1]
# - 记录 Ak = A[k/2-1] ,Bk = B[k/2-1] 根据以下判断:
# -- 1.Ak < Bk ,A 中存在 k/2-1 个比 Ak 小的数,B中最多存在 k/2-1 个比 Ak 小的数
# --   所以累计最多有 k-2 个比 Ak 小的数,所以 A[0] - A[k/2-1] 都不可能是第 k 小的数,可以全部排除
# -- 2.同理,若Ak > Bk ,可以全部排除 B[0] - B[k/2-1]
# -- 3.Ak = Bk ,可以任选以上两种情形处理
# - 在排除了 k/2 个数字之后,我们原来想找的第 k 个小的数.在去除被排除的数之后,变为寻找第 k/2 个小的数
# - 重复以上逻辑直到找到目标值
def find_k(a, b, k):

    a_length = len(a) 
    b_length = len(b)

    # 记录数组 a 已经排除的长度
    exclude_a_len = 0
    # 记录数组 b 已经排除的长度
    exclude_b_len = 0

    # 循环
    while True:
        # 边界处理
        # 当数组 a 排除的数组长度已经达到 a 的总长度时,说明第 k 个小的数在 b 中
        if exclude_a_len == a_length:
            return b[exclude_b_len+k-1]
        # 当数组 b 排除的数组长度已经达到 b 的总长度时,说明第 k 个小的数在 a 中
        if exclude_b_len == b_length:
            return a[exclude_a_len + k - 1]
        # 如果 k 是 1 ,那么就去两个数组中,获取除了已经排除的数字之外的最小值
        if k==1:
            # 数组a,b已经是有序的
            return min(a[exclude_a_len],b[exclude_b_len])

        # 排除数字之后的第 k/2 个小的数的位置和数组长度作比较,取最小值,避免超出下标范围
        half = (int)(k / 2)
        a_index = min(exclude_a_len + half, a_length)-1
        b_index = min(exclude_b_len + half, b_length)-1

        # 数组 a 中第k/2个数
        a_half = a[a_index]
        # 数组 b 中第k/2个数
        b_half = b[b_index]

        if a_half <= b_half:
            # 情况 1 3
            # 更新要找的数字的位置
            k -= (a_index + 1 - exclude_a_len)
            # 更新数组 a 排除的长度
            exclude_a_len = a_index + 1
        else:
            # 情况2
            k -= (b_index + 1 - exclude_b_len)
            exclude_b_len = b_index + 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值