每日leetcode:寻找两个有序list(递增排列)的中位数(python)

最初的想法是对于L1和L2,长度各为len1,len2,各取他们的中位数m1,m2(因为L1和L2已经排序)(假设这里L1[m1]>L2[m2]),除开L1最大值小于L2的最小值这种特殊情况,则待求中位数一定位于L1[m1]与L2[m2]之间,然后再取L1[0,m1],L2[len2-m2,len2]这两段重复上面的操作。但是很明显这种想法是错误的,可以假设中值m位于L1[m1,len1-1]之间,那么只要在L2[m2,len2-1]之间存在多于(len1+len2)/2个大于m的数,这个假设就可以成立。

正确的思路是通过考虑到两个list之间的限制关系:很明显,这个问题最终会将两个list分别分为左右两堆,左边任意一堆小于右边任意一堆,而且左右两边的数字个数相同,我们可以假设左边是L1[0,,,i-1],L2[0,,,j-1],右边是L1[i,,,len1-1],L2[j,,,len2-1],很明显若len1+len2为偶数,则i+j-2 = len1-i+len2-j,但是考虑到奇数,我们可以处理为j=(len1+len2+1)/2,此时若长度之和为奇数,则左边堆比右边堆多一个。然后就是L1[i-1]<=L2[j],L2[j-1]<=L1[i]。然后就可以在L1中进行二叉树遍历。找到左边堆中最大的于右边堆中最小的,然后若长度和为奇数,返回左边堆最大的,否则返回左边堆最大的与右边堆最小的平均数。

基本思路是这样,但是考虑到i-1,i,j-1,j可能不存在的情况:也就是i<0,i>=len1这样的情况,就需要进行特殊处理:i<0意味着L1的最小值都比L2的最大值大,明显左边堆的最大值直接就取L2[j-1],因为左边堆中不会有L1的数字,同理若j<0左边堆的最大值直接就取L1[1-1];而i>=len1意味着L1的最大值都比L2的最小值小,右边堆的最小值直接就取L2[j],j>=len2类推。

def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        l1 = len(nums1)
        l2 = len(nums2)
        if l2 > l1:
            temp_nums1 = nums1
            temp_nums2 = nums2
        else:
            temp_nums1 = nums2
            temp_nums2 = nums1
        l1 = len(temp_nums1)
        l2 = len(temp_nums2)
        iMin = 0
        iMax = l1
        while True:
            i = (iMin+iMax) // 2
            j = (l1+l2+1) // 2 - i
            if i > iMin and temp_nums1[i-1] > temp_nums2[j]:
                iMax -= 1
            elif i < iMax and temp_nums2[j-1] > temp_nums1[i]:
                iMin += 1
            else:
                break
        if i == 0:
            maxLeft = temp_nums2[j-1]
        elif j == 0:
            maxLeft = temp_nums1[i-1]
        else:
            maxLeft = max(temp_nums1[i-1], temp_nums2[j-1])
        if (l1+l2)%2 == 1:
            return maxLeft
        if i == l1:
            minRight = temp_nums2[j]
        elif j == l2:
            minRight = temp_nums1[i]
        else:
            minRight = min(temp_nums1[i], temp_nums2[j])
        if (l1+l2)%2 == 0:
            return (maxLeft+minRight) / 2

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值