4.两个排序数组的中位数

版权声明:转载请记得声明 https://blog.csdn.net/qq_39268193/article/details/80256473

题目

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

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


示例1:

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

中位数是 2.0

示例2:

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

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


解析1:

直接简单粗暴,把两个数组合并在排序,复杂度为O(nlog(n)),但是很明显 复杂大于O(long(m+n))的,不是此题正解


我的代码

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        nums = nums1 + nums2
        nums = sorted(nums)
        length = len(nums)
        
        if length & 1:
            return nums[length//2]
        else:
            return (nums[length//2 - 1] + nums[length//2]) / 2


解析二:

我们再看,两个有序的数组,这不就是归并吗,通过!但复杂度O(n+m) 但还是要大于O(log(n+m)) , 也不是正解


我的代码

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        nums = self.merge(nums1, nums2)
        
        length = len(nums)
        
        if length & 1:
            return nums[length//2]
        else:
            return (nums[length//2 - 1] + nums[length//2]) / 2

        
    # 归并,将两个有序数组合并为一个有序数组
    def merge(self, a, b):
        nums =  []
        
        while a and b:
            if a[0] < b[0]:
                nums.append(a.pop(0))
            else:
                nums.append(b.pop(0))
        return nums + a + b

解析三:

虽然上面两种方法都可以通过,但很显然复杂度要大于题目要求的,如果要达到题目要求,我们得用二分思想

思路为下:

1.我们将问题转换为一个寻找第k大数的问题,这样中位数实际上就是第(len_1 + len_2) / 2 + 1大的数。即“寻找第k个元素”

2.令pa = k / 2,  pb= k - pa, 如果第一序列的第pa个元素 小于 第二序列第pb个元素 我们不确定二序列第pb个元素是大了还是小了,但一序列的前pb个元素肯定都小于目标,所以我们将第一个序列前p个元素全部抛弃,形成一个较短的新序列。k = k-pa

3.同理,如果第一个序列第p个元素大于第二个序列第q个元素,我们则抛弃第二个序列的前q个元素。k = k - pb

4.如此递归 当较短序列全被抛弃,则返回较长序列的第 k 个元素 或者出现第pa个元素和第pb个元素相等时,就说明中位数就是这个数, 还有刚好当k = 1 时 就返回min(a[0], b[0])


我的代码:

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        len_1 = len(nums1)
        len_2 = len(nums2)
        length = len_1 + len_2
        harf = length >> 1
        
        if length & 1:
            return self.find_kth(nums1, len_1, nums2, len_2, harf + 1)
        else:
            return (self.find_kth(nums1, len_1, nums2, len_2, harf) +
                self.find_kth(nums1, len_1, nums2, len_2, harf + 1)) / 2
        
    def find_kth(self, a, len_a, b, len_b, k):
        # 保持数组 a 的长度总是小于数组 b 的长度
        if len_a > len_b:
            return self.find_kth(b, len_b, a, len_a, k)
        if len_a == 0:
            return b[k-1]
        if k == 1:
            return min(a[0], b[0])
        pa = min(k >> 1, len_a)
        pb = k - pa
        if a[pa-1] < b[pb-1]:
            return self.find_kth(a[pa:], len_a-pa, b, len_b, k-pa)
        elif a[pa-1] > b[pb-1]:
            return self.find_kth(a, len_a, b[pb:], len_b-pb, k-pb)
        else:
            return a[pa-1]




猜你喜欢

转载自blog.csdn.net/qq_39268193/article/details/80256473