Leetcode4-寻找两个正序数组的中位数原理及代码实现

LeetCode4 hard

题目

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

给定两个大小为m和n的正序(从小到大)数组nums1和nums2.请你找出这两个正序数组的中位数,并且要求算法时间复杂度为O(log(m+n)).
示例图片

解题思路

1. 简单算法 O(m+n)

将两个数组合并成一个,利用自带的排序函数使合并后的数组有序。根据下标返回中位数。但这样时间复杂度是O(m+n),不符合题目要求。

class Solution:#64ms 33.73% O(m+n)
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        nums1.extend(nums2)
        nums1.sort()
        length=len(nums1)
        if length%2==0:
            return (nums1[length//2-1]+nums1[length//2])/2
        return nums1[length//2]
        
2. 二分法 O(log(m+n))

如果对时间复杂度要求有log,通常需要用到二分查找。
寻找中位数的问题实质上是寻找第k小的数。我们比较两个数组中第k/2小的数,较小的数及他之前的数一定不会是第k小的数,这样我们每次比较可以排除一半的数,达到了O(log(m+n))的时间复杂度。当然,有一些特殊情况需要单独考虑。

class Solution:#56ms 66.72% O(log(m+n))
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        def getKthMin(k:int, nums1: List[int], nums2: List[int])->int:
            #特殊情况1,某一个数组为空,则直接在另一个数据找到第k小的值
            if not nums1:
                return nums2[k - 1]
            if not nums2:
                return nums1[k - 1]
            #特殊情况2,k==1即返回最小值
            if k==1:
                return nums1[0] if nums1[0]<=nums2[0] else nums2[0]
	    #特殊情况3,第k//2个元素超过索引,则直接比较最后一个元素与另一个数据对应元素,此时排除的元素个数是len(较短数组),而不是k//2
            nums11, nums22 = nums1, nums2
            if k//2>len(nums2):
                nums11, nums22 = nums2, nums1
            if k//2>len(nums11):
                if nums11[-1]<=nums22[len(nums11)-1]:
                    k-=len(nums11)
                    return nums22[k - 1]
                else:
                    g=k-len(nums11)
                    return getKthMin(g, nums11, nums22[len(nums11):])

	    #正常情况,如果nums1的元素较小,则nums1位于比较位置之前的元素一定不是第k小的元素,被排除。下一次比较从nums1的下一个位置算起。
            if nums1[k//2-1]<=nums2[k//2-1]:
                g=k-k//2
                return getKthMin(g,nums1[k//2:], nums2)
            else:
                g=k-k//2
                return getKthMin(g, nums1, nums2[k//2:])
	#如果总长度为偶数,中位数则为二者平均值
        length=len(nums1)+len(nums2)
        if length%2==0:
            return (getKthMin(length//2, nums1, nums2)+getKthMin(length//2+1, nums1, nums2))/2
        else:
            return getKthMin(length // 2 + 1, nums1, nums2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值