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

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

题意

给定两个拍好序的数组,求两个数组合并后的中位数。

解题思路

  • 归并排序:将多个需要排序的数组合并成最终的数组,然后求中位数,那么它的时间复杂度则为(n+m)log(n+m)*,而题目的要求是log(n+m),可以看出应该是使用二分法来查找,较小的一方会直接丢弃掉;

  • 维护中位数的数组(两个,是考虑到可能总数是偶数的情况),通过0,1的下标记录下中间数;

  • 将两个数组合并到一个数组中,取该数组的中位数;

实现

class Solution:
   # k为要求的第几位数
   def findKthSmallest(self, A, B, k):
       lenA, lenB = len(A), len(B)
       # 保证数组A的长度是小的
       if lenA > lenB:
           return self.findKthSmallest(B, A, k)
       # 如果A长度为0,则直接将数组B的中位数返回
       if lenA == 0:
           return B[k-1]
       # 如果要求第一位数,直接取两个数组较小值???
       if k == 1:
           return min(A[0], B[0])

       # 找左边第pq个元素,右边第pb个元素
       pa = min(k//2, lenA); pb = k - pa
       # 缩小区间
       if A[pa-1] <= B[pb-1]:
           return self.findKthSmallest(A[pa:], B, pb)
       else:
           return self.findKthSmallest(A, B[pb:], pa)

   def findMedianSortedArrays(self, A, B):
       """
      :type A: List[int]
      :type B: List[int]
      :rtype: float
      """
       lenA, lenB = len(A), len(B)
       # 总和为奇数
       if (lenA + lenB) % 2 == 1:
           return self.findKthSmallest(A, B, (lenA + lenB)//2 + 1)
       else:
           return (self.findKthSmallest(A, B, (lenA + lenB)//2) + self.findKthSmallest(A, B, (lenA + lenB)//2 + 1)) * 0.5
         
def findMedianSortedArrays(self, nums1, nums2):
       """
      :type nums1: List[int]
      :type nums2: List[int]
      :rtype: float
      """
       # 维护两个中位数的数组
       medians = [0] * 2
       len1, len2 = len(nums1), len(nums2)
       mid = (len1 + len2) // 2
       index1, index2 = 0, 0
       # 防止数组越界,为了让一个数组执行完了以后,还能继续往下执行到下个数组的值,比如1,2和3,4
       nums1.append(float("inf"))
       nums2.append(float("inf"))

       while index1 + index2 <= mid:
           if nums1[index1] < nums2[index2]:
               medians[(index1 + index2) % 2] = nums1[index1]
               index1 += 1
           else:
               medians[(index1 + index2) % 2] = nums2[index2]
               index2 += 1
       
       # 如果个数是奇数,取中间结点的下标的值
       # 如果个数是偶数,说明两个都是中间结点,取和除2即可
       if (len1 + len2) % 2:
           return medians[mid % 2] * 1.0
       else:
           return sum(medians) / 2.0
         
def findMedianSortedArrays(self, nums1, nums2):
       """
      :type nums1: List[int]
      :type nums2: List[int]
      :rtype: float
      """
       all_nums = []
       len1, len2 = len(nums1), len(nums2)
       mid = (len1 + len2) // 2
       index1, index2 = 0, 0
       
       # 将两个数组合并到一个数组中
       while index1 < len1 and index2 < len2:
           if nums1[index1] < nums2[index2]:
               all_nums.append(nums1[index1])
               index1 += 1
           else:
               all_nums.append(nums2[index2])
               index2 += 1

       if index1 != len1:
           all_nums.extend(nums1[index1:])
       if index2 != len2:
           all_nums.extend(nums2[index2:])
       
       # 取最终的数组的中间数
       if (len1 + len2) % 2:
           return all_nums[mid] * 1.0
       else:
           return (all_nums[mid] + all_nums[mid - 1]) / 2.0
posted @ 2017-08-20 12:19  banananana  阅读(135)  评论(0编辑  收藏  举报