LeetCode0004. 寻找两个正序数组的中位数(还未解决, 不满足题目要求)

一. 题目
  1. 题目
    给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
    请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))
    你可以假设 nums1 和 nums2 不会同时为空。

  2. 示例
    在这里插入图片描述

二. 方法一: 合并求解(达不到题目要求的时间复杂度)
  1. 解题思路

  2. 解题代码

    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        len1 = len(nums1)
        len2 = len(nums2)
        # 如果两个列表都为空, 则返回0
        if len1 == 0 and len2 == 0:
        	return 0
        i, j = 0, 0
        # 从头开始比较两个列表中元素的大小
        while len1 != 0 and len2 != 0 and i < len(nums1) and j < len2:
        	# 如果nums1中当前元素大于等于nums2中的当前元素,
        	# 则将nums2中的当前元素插入到nums1的当前位置
            if nums2[j] <= nums1[i]:
                nums1.insert(i, nums2[j])
                # 并将nums2中的指针移到下一位
                j += 1
            # 否则, 将nums1中的指针移到下一位
            else:
                i += 1
        # 此时, nums1的指针已经指到最后一位, 但nums中还有元素未插入
        # 将nums2中剩余的元素插入到nums1的后面
        while len2 != 0 and j < len2:
            nums1.append(nums2[j])
            j += 1
    
        size = len(nums1)
        # 返回中位数
        if size % 2 == 1:
            return nums1[int((size - 1) / 2)]
        else:
            return (nums1[int(size / 2 - 1)] + nums1[int(size / 2)]) / 2
    
  3. 分析
    时间复杂度: O(m+ n)
    空间复杂度: O(n)

三. 方法二: 奇数求解(达不到题目要求的时间复杂度)
  1. 解题思路

    1. 我们不需要将两个数组真的合并,我们只需要找到中位数在哪里就可以了。

    2. 用 len 表示合并后数组的长度

      1. 如果是奇数,我们需要知道第 (len+1)/2 个数就可以了,如果遍历的话需要遍历 int(len/2 ) + 1 次。
      2. 如果是偶数,我们需要知道第 len/2和 len/2+1 个数,也是需要遍历 len/2+1 次。所以遍历的话,奇数和偶数都是 len/2+1 次。
    3. 返回中位数的话,奇数需要最后一次遍历的结果就可以了,偶数需要最后一次和上一次遍历的结果。

    4. 所以我们用两个变量 left 和 right,right 保存当前循环的结果,在每次循环前将 right 的值赋给 left。这样在最后一次循环的时候,left 将得到 right 的值,也就是上一次循环的结果,接下来 right 更新为最后一次的结果。

    5. 用 aStart 和 bStart 分别表示当前指向 A 数组和 B 数组的位置。

      1. 如果 aStart 还没有到最后并且此时 A 位置的数字小于 B 位置的数组,那么就可以后移了。也就是aStart<m&&A[aStart]< B[bStart]。
      2. 如果 B 数组此刻已经没有数字了,继续取数字 B[ bStart ],则会越界,所以判断下 bStart 是否大于数组长度了,这样 || 后边的就不会执行了,也就不会导致错误了,所以增加为 aStart<m&&(bStart) >= n||A[aStart]<B[bStart]) 。
  2. 解题代码

    def findMedianSortedArrays(nums1: List[int], nums2: List[int]):
        len1 = len(nums1)
        len2 = len(nums2)
        size = len1 + len2
        # left 用于存放遍历的前一个值
        # right 用于存放遍历的当前值
        left, right = -1, -1
        # aStart, bStart 用于表示指针的移动
        aStart, bStart = 0, 0
        # 只需要遍历 size/2 + 1次就遍历到中位数了
        for num in range(size // 2 + 1):
            # 每一次循环, 就将当前的值赋值给前一个值
            left = right
    
            # 当nums1还没有遍历到最后, 且
            # aStart指向的值小于bStart执行的值 或者 nums2已经遍历到最后了
            # 此时就移动nums1
            if aStart < len1 and (bStart >= len2 or nums1[aStart] < nums2[bStart]):
                right = nums1[aStart]
                aStart += 1
            # 否则就移动nums2
            else:
                right = nums2[bStart]
                bStart += 1
        # 如果列表长度和为偶数, 则中位数是中间两个数之和再求平均
        if size % 2 == 0:
            return (left + right) / 2
        # 如果类别长度为奇数, 则中位数是最中间的那个数
        else:
            return right
    
  3. 分析
    时间复杂度: O(m + n)
    空间复杂度: O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值