1. 程式人生 > >LeetCode千題斬之找出兩個有序陣列的中位數

LeetCode千題斬之找出兩個有序陣列的中位數

題目: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.

           有兩個排好序的陣列(可以假設兩個陣列均為非空),找到這兩個陣列元素合在一起的中位數。執行時間複雜度應該在O(log (m+n)).

思路:首先要深刻理解一下中位數的含義,就是把一個數組分成兩個相同長度的子陣列,左邊陣列元素均小於右邊陣列元素。

           兩個陣列記為A與B,大小為m與n,先假設m<n。

           則相當於可以使用兩塊木板把陣列A,B分成兩部分,

          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=(m+n+1)/2(偶數時left_part元素個數為總數一半,總數目為奇數時left_part元素個數為一半向上取整),

     且len(left_part)=len(right_part)

        max(left_part)≤min(right_part)

          則成功滿足了題目條件,median=max(left_part)+min(right_part)/2​。

         於是可選擇變數i,j,因為對陣列A的劃分只有0,1,2...m中(想像成往元素中間插木板),所有i取0~m,i+j=(m+n+1)/2。使用二分法進行迴圈。

         考慮了大體的思路後需要考慮可能出現的極端情況,最直接的想法就是兩塊木板插入的位置剛好在陣列首與尾,此時將會有陣列A或B劃分後左右一端為空的情況。程式碼如下。


def findMedianSortedArrays( nums1, nums2):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: float
    """
    len1=len(nums1)
    len2=len(nums2)   #預設len2<=len1
    halflen=int((len1+len2+1)/2)
    if len1<len2:
        nums1,nums2,len1,len2=nums2,nums1,len2,len1 #交換num1與nums2
    imin,imax=0,len2
    while imin<=imax:
        i = int((imin + imax) / 2)
        j = halflen - i
        print(i,j)
        if i<len2 and nums1[j-1]>nums2[i]:
            imin+=1
        elif i>0 and nums2[i-1]>nums1[j]:
            imax-=1
        else:
            if i == 0:
                max_of_left = nums1[j - 1]
            elif j == 0:
                max_of_left = nums2[i - 1]
            else:
                max_of_left = max(nums1[j- 1], nums2[i - 1])

            if (len1 + len2) % 2 == 1:
                return max_of_left

            if i == len2:
                min_of_right = nums1[j]
            elif j == len1:
                min_of_right = nums2[i]
            else:
                min_of_right = min(nums1[j], nums2[i])

            return (max_of_left + min_of_right) / 2.0