刷LeetCode时候做的困难题,确实比简单和中等多花了很多时间啊~
4.寻找两个有序数组的中位数
给定两个大小为m和n的有序数组nums1和nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设nums1和nums2不会同时为空。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class Solution: def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: length = len(nums1)+len(nums2) m,n = len(nums1),len(nums2) l,r = max(0,length//2-n),min(length//2,m) if length%2==0: p,q = length//2-1,length//2 else: p,q = length//2,length//2 if m==0: return (nums2[p]+nums2[q])/2 if n==0: return (nums1[p]+nums1[q])/2 while l<=r: mid1 = (l+r)//2 mid2 = length//2-mid1 if mid1==0: lmax = nums2[mid2-1] elif mid2==0: lmax = nums1[mid1-1] else: lmax = max(nums1[mid1-1],nums2[mid2-1]) if mid1==m: rmin = nums2[mid2] elif mid2==n: rmin = nums1[mid1] else: rmin = min(nums1[mid1],nums2[mid2]) if rmin>=lmax: return (rmin+lmax)/2 if length%2==0 else rmin else: if nums1[mid1-1]==lmax: r = mid1-1 else: l = mid1+1
|
注:这是第一道困难题目,理解题意就花了很长时间。第一反应是排序再直接找中位数,但是两个数组归并排序到不了log(m+n)
的复杂度。这个是二分查找的变形,我们将两个数组分别分成左右两部分,两个左半部分合并,两个右半部分合并。因为中位数的位置是确定的,所以只需要在nums1上找位置即可确定nums2的位置。然后就是判断左半部分最大是不是小于右半部分最小。如果小于就成功,否则根据nums1左半部分的最大是否为左半部分最大,调整下一次二分查找的区间。第一次提交错误的地方在于没有定好l,r
的区间,因为这个和nums1及nums2的长度直接相关,不然会出现下标越界。