4. 寻找两个正序数组的中位数(hard,但很受用,解决了两个数组的topk问题)

首先是找出两个正序数组并起来的topk,就自然可以求出中位数啦!

怎么求topk?
分三种情况:k <=短数组长度, 短数组长度<k<=长数组长度, k>=长数组长度
三种情况都可以简化数组,去除不可能成为topk的元素
目的是化为 “两个等长数组求上分位数”等价。也就是求出这两个等长数组的上分位数就相当于求出了topk。
这个目的就涉及了两个问题,一个是怎么化成这种形式,另一个就是怎么求两个等长数组的上分位数?

怎么化成这种形式:
1、k <=短数组长度
2、短数组长度<k<=长数组长度
3、k>=长数组长度

怎么求两个等长数组的上分位数?本质也是去掉不可能是上分位数的数字,去掉之后递归这两个数组,知道两个数组长度为1。但当单个数组长度是奇数,递归可能会提前结束。
1、当单个数组的长度是偶数
[1,2,3,4] [1,2]
--------------->
[1,2,3,4] [3,4]
2、当单个数组的长度是奇数

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        import copy
        # 首先是将中位数转为求top k
        # 然后转化成等长数组求上分位数
        def topK_num(array1, array2, k):
            
            def lower_median(arr1, arr2):
                if len(arr1) != len(arr2):
                    raise Exception("长度不等错误") 
                length = len(arr1) 
                # 递归终止条件,返回上中位数

                if length == 1:
                    return min(arr1[0], arr2[0])

                # 当数组长度为偶数
                if length & 1 == 0:  
                    # arr1和arr2的上分位数比较
                    median = int(length/2)
                    if arr1[median-1] == arr2[median-1]:
                        return arr1[median-1]
                    elif arr1[median-1] < arr2[median-1]:
                        temp = copy.deepcopy(arr1)
                        arr1 = arr2
                        arr2 = temp
                    if arr1[median-1] > arr2[median-1]:
                        
                        lower_median_num = lower_median(arr1[:median],arr2[median:])

                # 当数组长度为奇数
                else:   
                    if arr1[length//2] == arr2[length//2]:
                        return arr1[length//2]
                    elif arr1[length//2] < arr2[length//2]:
                        temp = copy.deepcopy(arr1)
                        arr1 = copy.deepcopy(arr2)
                        arr2 = temp
                    if arr1[length//2] > arr2[length//2]:
                        
                        arr1 = arr1[:length//2]
                        arr2 = arr2[length//2:]
                        # 此时不等长,要判断删掉arr2的第一个元素
                        # 需要手动判断一下arr2的第一个元素与arr1的最后一位谁大
                        if arr2[0] > arr1[-1]:
                            return arr2[0]
                        else:
                            lower_median_num = lower_median(arr1,arr2[1:])
                return lower_median_num
                        
            # 确保array1是较短的那个数组
            length_arr1 = int(min(len(array1), len(array2)))
            length_arr2 = int(max(len(array1), len(array2)))
            if len(array1) > len(array2):
                temp = copy.deepcopy(array1)
                array1 = copy.deepcopy(array2)
                array2 = temp 
            total_length = length_arr1 + length_arr2
            if not length_arr1 and not length_arr2:
                return None
            elif not length_arr1:
                if length_arr2 & 1 == 0:
                    median = int(length_arr2/2)
                    return (array2[median-1] + array2[median])/2
                else:
                    return array2[length_arr2//2]

            k = int(k)
            # 分三种情况

            if k <= length_arr1:
                
                array1 = array1[:k]
                array2 = array2[:k]

                return lower_median(array1, array2)
            elif k > length_arr1 and k <= length_arr2:
                
                array2 = array2[k-length_arr1-1:k]
                if array2[0] >= array1[-1]:
                    return array2[0]
                else:
                    array2 = array2[1:]
                    return lower_median(array1, array2)
            elif k > length_arr2:
                array2 = array2[k-length_arr1-1:]
                if array1[0] >= array2[-1]:
                    return array1[0]
                elif array2[0] >= array1[-1]:
                    return array2[0]
                else:
                    array1 = array1[1:]
                    array2 = array2[1:]
                    return lower_median(array1, array2)

        # 开始求中位数,就是判断取top几
        if (len(nums1) + len(nums2)) & 1 != 0:
            return topK_num(nums1, nums2, int((len(nums1) + len(nums2))//2+1))
        else:
            lower = topK_num(nums1, nums2, int((len(nums1) + len(nums2))/2))
            
            higher = topK_num(nums1, nums2, int((len(nums1) + len(nums2))/2+1))
            
            return (lower + higher) / 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值