LeetCode4:Median of Two Sorted Arrays

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)).

You may assume nums1 and nums2 cannot be both empty.

Example 1:

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

The median is 2.0

Example 2:

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

The median is (2 + 3)/2 = 2.5

LeetCode:链接

第一种方法:设num1的长度为m,nums2的长度为n,将问题转化为在两个排好序的数组中找第k=(m+n+1)/2的元素(若总数是偶数还需要找第K+1大的元素)

为了方便说明,假设 m<=n

每次a_m= min(m, k/2),b_mid = k – a_m,然后比较A中第a_m个元素和B中第b_m个元素,即A[a_m – 1]和B[b_m – 1],

  • 若A[a_m – 1] < B[b_m – 1],则说明第k小的元素不可能出现在A中的前a_m个,也不可能出现在B中的b_m之后。即在A[a_m:],B[:b_m + 1]中查找第k – a_m元素。(因为a_m + b_m = k,不可能出现在A的a_m个的话,B中的前b_m个元素已经足够k-a_m个了)
  • 若A[a_m – 1] >B[b_m – 1],则说明第k小的元素不可能出现在B中的前b_m个,也不会再A中的a_m之后,因此,在A[a_m + 1],B[b_m:]中查找k – b_m元素
  • 若相等,则找到了

复杂度O(log(m + n))

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        def find_k_th(k, a, b):
            m, n = len(a), len(b)
            if m > n:
                return find_k_th(k, b, a)
            if m == 0:
                return b[k-1]
            if n == 0:
                return a[k-1]
            if k == 1:
                return min(a[0], b[0])

            a_mid = min(k//2, m)
            b_mid = k - a_mid
            if a[a_mid-1] < b[b_mid-1]:
                return find_k_th(k-a_mid, a[a_mid:], b[:b_mid+1])
            elif a[a_mid-1] > b[b_mid-1]:
                return find_k_th(k-b_mid, a[:a_mid+1], b[b_mid:])
            else:
                return a[a_mid-1]
        m, n = len(nums1), len(nums2)
        k = (m + n + 1) // 2
        ans = find_k_th(k, nums1, nums2)
        if (m+n)&1:
            return ans
        else:
            ans = ans + find_k_th(k+1, nums1, nums2)
            return ans/2.0

第二种方法:

同样假设m <= n,我们需要找到的是一个i和一个j,这两个下标分别将两个数组划分为左右两部分:

1

2

3

          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]

当然i未必和j相等。若能找到一个这样的i和j,满足:

  • i + j = (m + n + 1) / 2
  • 并且a[i-1] < a[j], b[j-1] < b[i]

这两个条件使得a[i – 1], 和b[j – 1]恰好为在中间的数,谁大谁就是中位数,若m + n为,偶数,则还要考虑a[i]和a[j]中较小的数。(i=0或j=0或i = m或j = n的特殊情况之后讨论)

因此,可以二分枚举i,起始范围left= 0, right  = m,则j = (m + n + 1) / 2 – i,

  • 若a[i] < b[j – 1],则说明i太小,要增大i,left = i + 1
  • 若a[i – 1] > b[j],说明i太大,要减小i,right = i – 1
  • 否则找到了i和j的正确位置,看m + n是奇数的话直接返回max(a[i – 1], b [j- 1])即可,否则为(max(a[i – 1], b [j- 1]) + min(a[i], b[j])) / 2

现在讨论边界情况:

  • i = 0时,此时j = (m + n + 1) / 2,此时即可假设a[i-1]必定小于b[j],只需要看 a[i] > b[j -1]即可
  • i = m时,此时j = (n – m + 1) / 2 > 0,也可以说a[i] > b[j – 1],只需要看a[i – 1] < b[j]即可
  • j = 0和j = n同理
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        m , n = len(nums1), len(nums2)
        if m > n:
            nums1, nums2, m , n = nums2, nums1, n, m 

        imin, imax, half_len = 0, m, (m+n+1)//2
        while imin <= imax:
            i = (imin + imax) // 2
            j = half_len - i 
            if i < m and nums1[i] < nums2[j-1]:
                imin += 1
            elif i > 0 and nums1[i-1] > nums2[j]:
                imax -= 1
            else:
                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) & 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

猜你喜欢

转载自blog.csdn.net/mengmengdajuanjuan/article/details/84341623