LeetCode:4. Median of Two Sorted Arrays - Python

问题描述:

4. 寻找两个有序数组的中位数

给定两个大小为mn的有序数组nums1nums2

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

你可以假设nums1nums2不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5

问题分析:

今天下午,zhongkeyuan面试题目。
方法1:
(1)先把两个数组合并,然后排序,直接求出结果。
(2)时间复杂度可以理解为: O((n+m)log(n+m)) 或者 O(nlogn) 也行,都是一个数量级。
(3)很显然,没有满足题目要求。


方法2:切割法 - 参考官方解答进行梳理

(1) 为了方便,nums1nums2AB 代替。分别从AB中找一个位置ij,把两个数组分别开为两部分,如下:

      left_part          |        right_part
A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]
B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

根据中位数的性质,很容易得到两个条件:

1、 l e n ( l e f t _ p a r t ) = l e n ( r i g h t _ p a r t ) len(left\_part)=len(right\_part)
2、 max ( left_part ) min ( right_part ) \max(\text{left\_part}) \leq \min(\text{right\_part}) max ( A [ i 1 ] , B [ j 1 ] ) min ( A [ i ] , B [ j ] ) \max(A[i-1], B[j-1]) \leq \min(A[i], B[j])

进一步可以得出:

m e d i a n = ( m a x ( l e f t _ p a r t ) + m i n ( r i g h t _ p a r t ) ) / 2 median= (max(left\_part)+min(right\_part))/2

(2) 如何确定ij?,接着上面推导,可以得出下面两个条件

1、 i + j = m i + n j i+j=m−i+n−j 或者, i + j = m i + n j + 1 i+j=m - i + n - j + 1

如果 n>=m,此时, i = [ 0... m ] i =[ 0 ...m] j = ( n + m + 1 ) / 2 i j = (n+m+1)/2 - i ,(始终保持n大,这样为了是j的非负性)

2、 B [ j 1 ] A [ i ] a n d A [ i 1 ] B [ j ] B[j-1] \leq A[i] and A[i−1] \leq B[j]

这一过程,就可以通过二分法来查找来确定 i 的值了

(3) 最后就根据n+m的奇偶性,返回中位数,即可。时间复杂度 O(log min(n,m))

Python3实现:

# 方法 1
# 时间复杂度 O(nlogn)
# 排序法

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):

        nums = sorted(nums1 + nums2)  # 合并排序
        if len(nums) % 2 == 0:
            return (nums[len(nums) // 2] + nums[len(nums) // 2 - 1]) / 2
        else:
            return nums[len(nums) // 2]


if __name__ == '__main__':
    nums1, nums2 = [1, 3], [3, 4]
    solu = Solution()
    print(solu.findMedianSortedArrays(nums1, nums2))
# 方法 2
class Solution:
    def findMedianSortedArrays(self, nums1, nums2):

        m, n = len(nums1), len(nums2)
        if m > n:
            nums1, nums2, m, n = nums2, nums1, n, m  # 保持 n 始终大于 m
        if n == 0:
            return None

        imin, imax, half_len = 0, m, int((m + n + 1) / 2)
        while imin <= imax:
            i = int((imin + imax) / 2)
            j = half_len - i
            # 确定 i j 两个值
            if i < m and nums2[j - 1] > nums1[i]:  # 现在说名 i 太小,应该增加
                imin = i + 1
            elif i > 0 and nums1[i - 1] > nums2[j]:  # 现在说名 i 太大,应该减小
                imax = i - 1

            else:
                # i 的值已经确定,现在找中间值

                if i == 0:  # 确定左边界情况
                    max_of_left = nums2[j - 1]
                elif j == 0:
                    max_of_left = nums1[i - 1]
                else:
                    max_of_left = max(nums1[i - 1], nums2[j - 1])

                if (m + n) % 2 == 1:  # 奇数的情况下
                    return max_of_left

                if i == m:  # 确定右边界情况
                    min_of_right = nums2[j]
                elif j == n:
                    min_of_right = nums1[i]
                else:
                    min_of_right = min(nums1[i], nums2[j])

                return (max_of_left + min_of_right) / 2.0


if __name__ == '__main__':
    nums1, nums2 = [1, 3], [3, 4]
    solu = Solution()
    print(solu.findMedianSortedArrays(nums1, nums2))

声明: 总结学习,有问题或不妥之处,可以批评指正哦。

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

猜你喜欢

转载自blog.csdn.net/XX_123_1_RJ/article/details/84572284
今日推荐