leetcode题解:寻找两个正序数组的中位数

2022/01/17 leetcode 算法 共 1616 字,约 5 分钟

题目链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

题解基本思想来源于https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/的解法三,只是在他的基础上写写自己的见解。

首先这道题要求的时间复杂度是O(log(m+n))可以猜测到只有二分查找可以达到。按照题解,我们把寻找中位数当作寻找第k小的数的一个特例。

在寻找第k小的数的过程中,我们可以每次排除k/2个数,其过程如下:

image.png

我们比较两个数组k/2位置上的数的大小,可以知道3<4,由此我们知道(1,2,3)一定不是第7个数。由此排除第二个数组k/2个元素,接下来我们继续:

image.png

此时我们已经排除了k/2个元素,接下来在数组中寻找的应该是第k-k/2个小的数,所以k从7变为了4。此时我们再比较第k/2个元素,也就是3和5,得到3<5可以知道(1,3)能排除掉。

image.png

步骤同上,不同的是此时我们比较的4和4相等,此时排除掉任意一个数组的数字都可以。不妨排除下面一行的数组:

image.png

最后的结果为4。

另一种情况当循环进行时有一个数组全部排除,那我们就可以只看这一个数组了,计算更简单:

image.png

image.png

根据上述的思想来写代码,值得注意的是在总数为偶数的情况下,我们需要找两个数,而在我们循环的过程中,如我们已经找到了第(m+n)/2-1小的数,找到第(m+n)/2小的数只需要再在基础上比较一次就可以,不需要再从头计算。代码实现如下:

class Solution(object):
    def getKth(self, nums1, st1, ed1, nums2, st2, ed2, k):
        len1 = ed1 - st1 + 1
        len2 = ed2 - st2 + 1
        if st1 > ed1:
            return st1, ed1, st2+k,ed2, nums2[st2+k-1]
        if st2 > ed2:
            return st1+k, ed1, st2, ed2, nums1[st1+k-1]
        if k==1:
            if nums1[st1] < nums2[st2]:
                return st1+1, ed1, st2, ed2, nums1[st1]
            else:
                return st1, ed1, st2+1, ed2, nums2[st2]
        i = st1 + min(len1, k/2) - 1
        j = st2 + min(len2, k/2) - 1
        if nums1[i] < nums2[j]:
            return self.getKth(nums1, i+1, ed1, nums2,st2, ed2, k-(i-st1+1))
        else:
            return self.getKth(nums1, st1, ed1, nums2, j+1, ed2, k-(j-st2+1))
        return st1, ed1, st2, ed2, x

    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        n1 = len(nums1)
        n2 = len(nums2)
        # tag==True时是奇数,否则是偶数
        tag = True
        if (n1+n2)%2 == 0:
            tag = False
        # k为第k小的数,从1开始计数,如果是偶数需要求第k小和第k+1小的数
        k = (n1+n2+1)/2
        # 之所以这样设计是想减少第二次计算时的重复操作
        st1, ed1, st2, ed2, x = self.getKth(nums1,0,n1-1,nums2,0,n2-1,k)
        if tag:
            return x
        else:
            _, _, _, _, y = self.getKth(nums1,st1,ed1,nums2,st2,ed2,1)
            return (x + y) / 2.0

文档信息

Search

    Table of Contents