Leetcodeアルゴリズム-4、2つの秩序配列の中位数


タイトル
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.
配列(昇順)された配列nums 1とnums 2が2つあり、大きさはそれぞれmとnである.2つの配列の中位数を見つける必要があります.時間的複雑度はO(log(m+n))である必要がある.2つの配列が同時に空になることはありません.
例:Example 1:nums 1=[1,3]nums 2=[2]The median is 2.0
Example 2: nums1 = [1, 2] nums2 = [3, 4] The median is (2 + 3)/2 = 2.5
構想
2つの配列は秩序正しく、集計ソートを思い出しました.2つのシーケンスを組み合わせてソートするには、2つのポインタで2つの配列をそれぞれスキャンし、ポインタ+1のたびにサイズを比較する必要があります.この問題は直接集計ソートを用いて中位数を見つけることができるが,この複雑さはO(m+n)であり,条件を満たさない.この問題は中位数を見つけるだけで、他の要素がソートされるかどうかは重要ではありません.そのため、2つのポインタは毎回+1する必要はありません.毎回最適な値を追加して、全体の複雑さを最小限に抑えます.この適切な値は,一般に終点までの数ビットの半分に等しいので,複雑度はO(log(m+n))である.
python実装
# -*- coding: utf-8 -*-

def findMedianSortedArrays(nums1, nums2):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: float

      :
             ,         :              ,                ,    +1     。
                 ,       ,        O(m+n),     。
                 ,            ,  ,         +1,            ,         。
    """

    def fun_rec(nums1, i, nums2, j, k):
        '''
                       i+j+k   。         i   j ,           k   。
        '''

        #       
        if i == len(nums1):
            return nums2[j+k-1]
        if j == len(nums2):
            return nums1[i+k-1]
        if k == 1:
            return min(nums1[i], nums2[j])

        #                     ,               ,               
        if len(nums1) - i > len(nums2) - j:
            return fun_rec(nums2, j, nums1, i, k)

        #        i j  ,      k/2,      ,         ,            。
        ii = i + int(k/2)
        ii = min(ii, len(nums1)) #     
        jj = i+j+k-ii #    (ii-i)+(jj-j) == k,  ii jj        k,                    ,       k  
        if nums1[ii-1] == nums2[jj-1]: #   ,      k  
            return nums1[ii-1]
        if nums1[ii-1] < nums2[jj-1]: #      ,      k  ,   ii  
            return fun_rec(nums1, ii, nums2, j, k+i-ii) #      fun_rec     2、4、5        i+j+k
        return fun_rec(nums1, i, nums2, jj, k+j-jj)

    #           
    total = len(nums1) + len(nums2)
    if total % 2 == 1: #   ,           
        return fun_rec(nums1, 0, nums2, 0, int((total+1)/2))
    else: #   ,           
        return (fun_rec(nums1, 0, nums2, 0, int(total/2)) + fun_rec(nums1, 0, nums2, 0, int(total/2+1))) / 2

def findMedianSortedArrays2(nums1, nums2):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: float

             ,       ,            ,         。
      : fun_rec   k       k    k+1  。

    """

    def fun_rec(nums1, i, nums2, j, k):
        '''
                       i+j+k        。         i   j ,           k   。
        '''

        #       
        if i == len(nums1):
            return (nums2[j+k-1], nums2[j+k])
        if j == len(nums2):
            return (nums1[i+k-1], nums1[i+k])
        if k == 1:
            if nums1[i] < nums2[j]:
                return (nums1[i], find_next(nums1, i, nums2, j-1))
            else:
                return (nums2[j], find_next(nums2, j, nums1, i-1))

        #                     ,               ,               
        if len(nums1) - i > len(nums2) - j:
            return fun_rec(nums2, j, nums1, i, k)

        #        i j  ,      k/2,      ,         ,            。
        ii = i + int(k/2)
        ii = min(ii, len(nums1)) #     
        jj = i+j+k-ii #    (ii-i)+(jj-j) == k,  ii jj        k,                    ,       k  
        if nums1[ii-1] == nums2[jj-1]: #   ,      k  
            return (nums1[ii-1], find_next(nums1, ii-1, nums2, jj-1))
        if nums1[ii-1] < nums2[jj-1]: #      ,      k  ,   ii  
            return fun_rec(nums1, ii, nums2, j, k+i-ii) #      fun_rec     2、4、5        i+j+k
        return fun_rec(nums1, i, nums2, jj, k+j-jj)

    def find_next(nums1, i, nums2, j):
        '''
        nums1      i,nums2      j。
           nums1[i]         。
        '''
        if i == len(nums1) - 1:
            return nums2[j+1]
        return min(nums1[i+1], nums2[j+1])

    #           
    if len(nums1)== 0 and len(nums2) == 1:
        return nums2[0]
    if len(nums2)== 0 and len(nums1) == 1:
        return nums1[0]    
    total = len(nums1) + len(nums2)
    result = fun_rec(nums1, 0, nums2, 0, int((total+1)/2))
    if total % 2 == 1: #   ,           
        return result[0]
    else: #   ,           
        return (result[0]+result[1])/2

if '__main__' == __name__:
    nums1 = [1, 3]
    nums2 = [2]
    print(findMedianSortedArrays2(nums1, nums2))

    nums1 = [1, 2]
    nums2 = [3, 4]
    print(findMedianSortedArrays2(nums1, nums2))