寻找两个正序数组的中位数Python解法

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

例:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

# 1 暴力解法:合并,排序,直接查找,时间复杂度O((m+n)log (m+n))

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        for i in range(len(nums2)):
            nums1.append(nums2[i])
        nums1.sort()
        num = len(nums1)
        k = int(num/2)
        if (num & 1) == 0:
            return ((nums1[k]+nums1[(k-1)])/2)
        else:
            return (nums1[k])

# 2 合并两个有序数组,只用合并到中值即可。时间复杂度O((m+n))

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        m = len(nums1)
        n = len(nums2)
        lens = m + n
        left, right = -1, -1  # 分割线左右两边的值
        aStart, bStart = 0, 0  # 两个数组的开始下标
        
        for i in range(lens//2 + 1):  # 只用遍历到中值即可
            left = right  # 右边界赋值给左边界
            if aStart < m and (bStart >= n or nums1[aStart] < nums2[bStart]):  # 1数组还有值,并且1数组当前下标对应的值小于2数组当前下标对应的值或者2数组已经遍历完毕
                right = nums1[aStart]  # 则将1数组当前下标对应的值赋给右边界
                aStart += 1  # 下标右移一位,判断下一个
            else:  # 与上个判断类似
                right = nums2[bStart]
                bStart += 1


        if (lens & 1) == 0:  # 按位与运算判断长度奇偶
            return (left+right)/2.0  # 为偶数的情况
        else:
            return right

# 二分法,同样查询一半的值即可,每个数组判断一半,将较小的一半直接过滤,因为是有序数组,直接判断中值即可,不必一一比较,时间复杂度为O(log (m+n))

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:

        def getK(k):  # k值,需要查询的第k大的值
            id1, id2 = 0, 0  # 数组1的下标,数组2的下标
            while True:
                # 特殊情况
                if id1 == m:  # 数组1全部在中值左边
                    return nums2[id2 + k - 1]  # 在数组2的当前下标下直接加上剩余需要判断的值
                if id2 == n:  # 数组2全部在中值左边
                    return nums1[id1 + k - 1]  # 在数组1的当前下标下直接加上剩余需要判断的值
                if k == 1:  # k等于1时表明已经排除了小于中值的值,直接返回当前下标中较小的一方即可
                    return min(nums1[id1], nums2[id2])

                # 正常情况
                newid1 = min(id1 + k // 2 - 1, m - 1)  # 数组1需要判断的位置下标
                newid2 = min(id2 + k // 2 - 1, n - 1)  # 数组2需要判断的位置下标
                p1, p2 = nums1[newid1], nums2[newid2]  # 判断下标对应的值
                if p1 <= p2:  # 若数组1的当前判断值较小,则说明判断下标以及之前的值全部都在中值左边,全部排除
                    k -= newid1 - id1 + 1  # 需要判断的k值减少排除的值
                    id1 = newid1 + 1  # 数组1从去除的下标后一位重新开始
                else:  # 同理
                    k -= newid2 - id2 + 1
                    id2 = newid2 + 1
        
        m,  n = len(nums1), len(nums2)  # 数组1,数组2的长度
        Length = m + n  # 总长度
        if Length % 2 == 1:  # 若总数组长度为奇数
            return getK((Length + 1) // 2)  # 直接返回中值下标对应的值
        else:  # 若为偶数
            return (getK(Length // 2) + getK(Length // 2 + 1)) / 2  # 返回中值左右两边的值相加取平均

三种方法,如果对时间复杂度没有要求的话,暴力还是最通俗易懂,暴力yyds |ू・ω・` )

题目描述: 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组中位数。 示例 1: 输入:nums1 = [1,3], nums2 = [2] 输出:2.00000 解释:合并数组 = [1,2,3] ,中位数 2 示例 2: 输入:nums1 = [1,2], nums2 = [3,4] 输出:2.50000 解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5 示例 3: 输入:nums1 = [,], nums2 = [,] 输出:.00000 示例 4: 输入:nums1 = [], nums2 = [1] 输出:1.00000 示例 5: 输入:nums1 = [2], nums2 = [] 输出:2.00000 提示: nums1.length == m nums2.length == n <= m <= 100 <= n <= 100 1 <= m + n <= 200 -106 <= nums1[i], nums2[i] <= 106 解题思路: 首先,我们需要将两个数组合并成一个有序数组,然后再根据数组长度的奇偶性来计算中位数。 对于合并两个有序数组,我们可以使用双指针的方法,从头开始遍历两个数组,每次将较小的数放入新的数组中,直到其中一个数组遍历完毕,然后将另一个数组中剩余的数全部放入新的数组中。 对于计算中位数,我们需要分为两种情况: 当数组长度为奇数时,中位数为新数组的中间数。 当数组长度为偶数时,中位数为新数组的中间两个数的平均数。 代码实现: class Solution: def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: # 合并两个有序数组 nums = [] i, j = , while i < len(nums1) and j < len(nums2): if nums1[i] < nums2[j]: nums.append(nums1[i]) i += 1 else: nums.append(nums2[j]) j += 1 if i < len(nums1): nums += nums1[i:] if j < len(nums2): nums += nums2[j:] # 计算中位数 n = len(nums) if n % 2 == : return (nums[n//2-1] + nums[n//2]) / 2 else: return nums[n//2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值