LeetCode练习题
4. 两个排序数组的中位数
描述
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
示例 1:
nums1 = [1, 3]
nums2 = [2]
中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
中位数是 (2 + 3)/2 = 2.5
思路
要求这么严格的时间复杂度,应该考虑二分求解。注意到这样一个事实:
nums1[0] nums1[1] ... nums1[i] | nums1[i+1] ... nums1[n]
nums2[0] nums2[1] ... nums2[j] | nums2[j+1] ... nums2[m]
如果分别把两个数组从上述位置切开,并满足如下条件:
- 左边数的个数=右边数的个数,即 (i+1)+(j+1)=(n−i)+(m−j) ( i + 1 ) + ( j + 1 ) = ( n − i ) + ( m − j )
- 左边的数均不大于右边的数,由于数组有序,即 max(nums1[i],nums2[j])⩽min(nums1[i+1],nums2[j+1]) m a x ( n u m s 1 [ i ] , n u m s 2 [ j ] ) ⩽ m i n ( n u m s 1 [ i + 1 ] , n u m s 2 [ j + 1 ] )
那么中位数就由
nums1[i],nums2[j],nums1[i+1],nums2[j+1]
n
u
m
s
1
[
i
]
,
n
u
m
s
2
[
j
]
,
n
u
m
s
1
[
i
+
1
]
,
n
u
m
s
2
[
j
+
1
]
这四个数确定。
因此只要二分
i
i
<script type="math/tex" id="MathJax-Element-4">i</script>即可。
需要注意一些特殊情况的判断。
代码
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
if len(nums1) > len(nums2):
temps = nums1
nums1 = nums2
nums2 = temps
if nums1 == []:
return nums2[(len(nums2)-1)//2]/1 if len(nums2)%2 != 0 else (nums2[(len(nums2)-1)//2]+nums2[(len(nums2)-1)//2+1])/2
nums1.insert(0, min(nums1[0], nums2[0])-1)
nums2.insert(0, nums1[0])
nums1.append(max(nums1[-1], nums2[-1])+1)
nums2.append(nums1[-1])
left1 = 1
right1 = len(nums1)
while left1 <= right1:
middle1 = (left1+right1)//2
middle2 = (len(nums1)+len(nums2))//2-middle1
if nums1[middle1-1] > nums2[middle2]:
right1 = middle1-1
elif nums2[middle2-1] > nums1[middle1]:
left1 = middle1+1
else:
break
if (len(nums1)+len(nums2))%2 == 0:
return (max(nums1[middle1-1], nums2[middle2-1])+min(nums1[middle1], nums2[middle2]))/2
return min(nums1[middle1], nums2[middle2])/1