4. 寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3] nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2] nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

1 暴力合并 ——— 双指针每次拿出最小的 O n1+n2 —— 不满足时复:log n1+n2

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        
        left_first = 0
        right_first = 0
        left_len = len(nums1)
        right_len = len(nums2)

        results = []

        while left_first < left_len and right_first < right_len:
            if nums1[left_first] < nums2[right_first]:
                results.append(nums1[left_first])
                left_first += 1
            elif nums1[left_first] >= nums2[right_first]:
                results.append(nums2[right_first])
                right_first += 1
        '''一定有一个列表先取完,另一个剩>=1个节点'''
        if left_first == left_len:  # 第2个列表先结束
            results += nums2[right_first:]
        elif right_first == right_len:  # 第1个列表先结束
            results += nums1[left_first:]
        ans = 0
        sumLen = left_len + right_len
        if sumLen % 2 == 0:
            tmp = (sumLen // 2) - 1
            ans = (results[tmp] + results[tmp+1]) / 2
        elif sumLen % 2 == 1:
            ans = results[sumLen // 2]

        return ans

2 [好背a] 分割线 + 二分查找 ———— O log m+n

强迫症击破:
1.让电脑自动识别条件,遇到什么if条件情况干什么即可,你不用管中间过程,最后符合 2个中位数的性质即可
     i j为0 或 n 时候,电脑自动if识别条件时会下标越界,所以你暴力直接拎出来告诉电脑该怎么 办即可
2 i j 为 0 nm时候:一定是最终的正确情况,此时时一方列表的所有元素全部大于或小于另一个列表中的所有元素
     【mh自猜:二分查找如果选到了0或n首尾,一定是最终结果了,因为如果它继续找的话要在中间才可以】
         另一个卡点:注意一方到头,另一方可不到头而是在中间,要用i j变量来动态访问max min,千万别用 0 n m 常数
    在这里插入图片描述
3 你不用担心一方到头是否左右对半分,j=f(i)的公式确保一定是对半分
    每个i对应的j是唯一的,所以当i到0或n的时候,j只有一个位置

def findMedianSortedArrays(nums1, nums2):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: float
    """
    n1 = len(nums1)
    n2 = len(nums2)
    # 保证第一个列表长
    if n1 > n2:
        n1,n2=n2,n1
        nums1,nums2=nums2,nums1

    imin = 0
    imax = n1

    while imin <= imax:  # 最后min=max 找到i 中位数直接在while里面算了方便
        i = (imin + imax) // 2
        j = (n1 + n2 + 1) // 2 - i

        if i < n1 and j > 0 and nums2[j-1] > nums1[i]:
            '''i太左'''
            imin += 1
        elif i > 0 and j < n2 and nums1[i-1] > nums2[j]:
            '''i太右'''
            imax -= 1
        else:
            '''i到达正确位置[注意:i=0 n 、j=0 m 一定是到最终位置了,因为此时是一个列表的所有元素都小于or大于另一个列表,你不用担心会左右数量不等,因为j的通过i的公式算出的,一定会两方对半分 ]'''
            # 左边的最值 [ij为0时候下标为负数越界,所以单独处理]
            if i == 0:
                max_of_left = nums2[j-1]
            elif j == 0:
                max_of_left = nums1[i-1]
            else:
                max_of_left = max(nums1[i-1], nums2[j-1])
            '''奇数不用考虑右边'''
            if (n1+n2)%2 == 1:
                return max_of_left

            if i == n1:
                min_of_right = nums2[j]  # 重要:i=n1时j在哪不一定,可不是nums1[0],应该写变量j
            elif j == n2:
                min_of_right = nums1[i]
            else:
                min_of_right = min(nums1[i], nums2[j])
            # '''偶数情况'''
            return (max_of_left + min_of_right)/2.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值