【leetcode】4. Median of Two Sorted Arrays

Problem Description

There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Examples

Solutions

核心思想是要将中位数的定义转化为“Dividing a set into two equal length subsets, that one subset is always greater than the other.”

key idea
代码思路:

  1. 第一种情况:两个list中有一个list为空;直接返回另一个list的中位数。
    这里有两种方式可解决元素个数的奇/偶需分开讨论的问题:1) 利用向下取整的trick,见代码;2)利用list[m]和list[~m];虽然本质是一样的
  2. 在算法中,根据‘two equal length subsets’的约束条件,我们只需loop查询两个list中的一个list即可,因为知道list1的cut的位置,根据等长约束,list2中cut的位置即可计算出。为了提高效率,使时间复杂度为 O(log(min(m,n)))(m, n分别为list1和list2的元素个数),不妨假设m<=n,不满足时调换两个list的位置即可
  3. 两个list均非空的情况;寻找使‘left is always greater than right’约束条件成立的list1中cut的位置。这里分三种情况:1) l1 > r2, cut1 需左移;2) l2 > r1, cut1 需右移 3) l1 < r2 and l2 < r1,stop。
  4. 有两种边缘特殊情况需考虑:1) max(nums1) < min(nums2) 2) min(nums1) > max(nums2);这里有一个非常巧妙的处理——在list两端分别添加MIN_VALUE和MAX_VALUE,便于将两种边缘特殊情况与普通情况一起处理
  5. 两个list均非空的情况返回结果时,需分别考虑元素个数奇偶情况:偶数——返回 (max(left)+min(right))/2;奇数——因为是向下取整,所以右边会多一个元素,返回min(right)即可。

详细代码如下: Github link

# Runtime: 92 ms
class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        MAX_VALUE = float('Inf')
        MIN_VALUE = -float('Inf')

        # 获取list元素个数
        m = len(nums1)
        n = len(nums2)
        if m == 0:  # nums1为空
            # 这里有个小trick
            # n为奇数时,nums2[int((n-1)/2)]和nums2[int(n/2)]是同一个数,即中位数
            # n为偶数时,nums2[int((n-1)/2)]和nums2[int(n/2)]分别为最中间的两个数
            # 这是因为int(n/2)是向下取整,int(1.5) == 1
            # 向下取整的功能也可以通过 '//' 运算符实现
            return float((nums2[int((n - 1) / 2)] + nums2[int(n / 2)]) / 2)
        if n == 0:  # 同理,nums2为空
            return float((nums1[(m - 1) // 2] + nums1[m // 2]) / 2)

        if m > n:  # 为了提高效率,保证进行loop遍历的是较短的list
            return Solution.findMedianSortedArrays(self, nums2, nums1)

        # 两个list均非空的情况
        # 割的范围初始化
        size = m + n
        CutL = 0
        CutR = m
        cut1 = m // 2  # 短list的割的位置

        while cut1 <= m:  # 寻找满足 l1<r2 and l2<r1的割的位置
            cut1 = (CutR - CutL) // 2 + CutL  # 短list的割的位置
            cut2 = size // 2 - cut1  # 长list的割的位置

            # 在list两端分别添加MIN_VALUE和MAX_VALUE,便于将两种边缘特殊情况与普通情况一起处理
            # 两种边缘特殊情况即:1. max(nums1)<min(nums2)  2. min(nums1)>max(nums2)
            # 获取割两边的值
            l1 = MIN_VALUE if cut1 == 0 else nums1[cut1 - 1]  # 相当于Java中的三目运算符'?:',只有当min(nums1)>max(nums2)时,l1取值MIN_VALUE
            l2 = MIN_VALUE if cut2 == 0 else nums2[cut2 - 1]  # 同上,其实取不到特殊情况?
            r1 = MAX_VALUE if cut1 == m else nums1[cut1]  # 只有当max(nums1)<min(nums2时,l1取值MIX_VALUE
            r2 = MAX_VALUE if cut2 == n else nums2[cut2]

            if l1 > r2:  # l1>r2, cut1需左移
                CutR = cut1 - 1
            elif l2 > r1:  # l2>r1, cut1需右移
                CutL = cut1 + 1
            else:  # 满足 l1<r2 and l2<r1
                if size % 2 == 0:  # 两个list的元素总个数为偶数
                    l = l1 if l1 > l2 else l2
                    r = r1 if r1 < r2 else r2
                    return float((l + r) / 2)
                else:  # 两个list的元素总个数为奇数
                    r = r1 if r1 < r2 else r2
                    return float(r)



这是符合时间复杂度要求O(log (m+n))的一种解法,实际时间复杂度为O(log(min(m,n)))

另外有一种时间复杂度为O(nlogn)的解法(考虑sort时间复杂度,虽然这两种解法都可以被accepted),代码简短,各取所需

# sample 88 ms submission
# 我提交这种方案仍然是 Runtime: 92 ms
class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        num = nums1 + nums2
        num = sorted(num)
        l = len(num)
        if l % 2 == 0:
            return (num[l//2-1]+num[l//2])/2*1.0
        else:
            return num[l//2]*1.0


# sample 92 ms submission
class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        nums1 += nums2
        nums1.sort()
        m = int(len(nums1) / 2)
        return (nums1[m] + nums1[~m]) / 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值