美文网首页
4. Median of Two Sorted Arrays

4. Median of Two Sorted Arrays

作者: oneoverzero | 来源:发表于2020-01-26 18:44 被阅读0次

    中位数的定义:如果某个有序数组长度是奇数,那么中位数就是最中间的那个数;如果是偶数,那么中位数就是最中间两个数字的平均值。

    拓展到两个有序数组的中位数:假设两个有序数组的长度分别为m和n,由于两个数组长度之和m+n的奇偶性不定,因此需要分情况来讨论。对于奇数的情况,直接找到最中间的数即可,偶数的话需要求最中间两个数的平均值。

    解这道题的关键并不是高超的算法,而是心中要有一副这样的图:
    (参考:https://juejin.im/post/5c8c9ec16fb9a049af6e2a0d

                  left side       |  right side 
    nums1:   A(0),A(1),...,A(i-1) | A(i),...,A(m-1)
    nums2:   B(0),B(1),...,B(j-1) | B(j),...,B(n-1)
    

    我们把两个数组看成一个整体,有一根竖线将其中的元素从中间分开,且左边的部分和右边部分的元素相同(总数为奇数情况下,左边比右边多 1 个元素),那么当 m+n 为偶数时,中位数为
    \frac{\max[A(i-1), B(j-1)] + \min[A(i), B(j)]}{2}
    m+n 为奇数时,中位数为
    \max[A(i-1), B(j-1)]
    我们都知道,左边的元素为 i+j 个,而左右两边元素相同,则
    i+j = \frac{m+n+1}{2}
    我们可以用 i 来表示 j ,则
    j = \frac{m+n+1}{2}-i
    所以,该题就变成了,在数组 A 中寻找一个 i ,使得 A(i) \ge B(j-1) ,且 A(i-1) \le B(j) 成立,这两个不等式的含义是,竖线右边最小的数一定不比左边最大的数小,满足该条件,我们就可以说找到了这个竖线。

    我们在找 i 的过程中,难免会碰到 A(i) < B(j-1) 的时候,此时我们需要将 i 向右移,使 A(i) 增大,当 i 右移,i 增大的同时,j 会减少,即 B(j-1) 的值会变小,这样操作 i 之后,会让我们更接近目标;同理,当 B(j) < A(i-1) 时,我们需要将 i 向左移。

    通过上面的分析,我们最终可以使用二分查找法来寻找这个 i 值,又由于二分查找的时间复杂度为 O(\log n) ,这种方法可以满足题目的要求。

    代码:(参考: https://leetcode.com/problems/median-of-two-sorted-arrays/discuss/2567/Python-O(log(min(mn))-solution

    class Solution(object):
        def findMedianSortedArrays(self, nums1, nums2):
            """
            :type nums1: List[int]
            :type nums2: List[int]
            :rtype: float
            """
            length = len(nums1) + len(nums2)
            return self.findKth(nums1, nums2, length//2) if length%2==1 else \
                  (self.findKth(nums1, nums2, length//2-1)+self.findKth(nums1, nums2, length//2))/2.0
        
        def findKth(self, A, B, k):
            if len(A) > len(B):
                A, B = B, A
            if not A:
                return B[k]
            if k == len(A) + len(B) - 1:
                return max(A[-1], B[-1])
            i = len(A) // 2
            j = k - i
            if A[i] > B[j]:
                return self.findKth(A[:i], B[j:], i)
            else:
                return self.findKth(A[i:], B[:j], j)
    

    这里要注意的是,在C++中切片操作如 A[i:] 的时间复杂度是 O(1) ,但是在Python中这样做的时间复杂度是 O(n) 。因此上述代码的时间复杂度应为 O(n \log (\min (m, n)))

    相关文章

      网友评论

          本文标题:4. Median of Two Sorted Arrays

          本文链接:https://www.haomeiwen.com/subject/wsojthtx.html