两个有序数列的中位数
力扣第四题,Median of Two Sorted Substring.
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.
思路
求中位数的过程可以看作分组和取中心两步。
分组
分组的条件是:
-
左侧组最大值小于等于右侧组最小值(左侧组每个元素都比右侧组中的小)
-
两组元素数量相等
条件2在元素总数是奇数时不可能满足。我们在这里需要做出抉择,多出的元素分给左侧组还是右侧组1。
取中心
中心的位置有两种情况:
- 两组最值的平均值(元素数是偶数)
- 某组的最值(元素数是奇数)
下面说明如何实现。
分组
这里选择将多出的元素分到左侧组:
def partion(arr1, arr2):
def is_safe_ref(arr, index):
return 0 <= index < len(arr)
def improve(imin, imax):
i = (imin + imax) // 2
j = (m + n + 1) // 2 - i # len(left) >= len(right)
if is_safe_ref(arr1, i - 1) and is_safe_ref(arr2, j) and arr1[i - 1] > arr2[j]:
return improve(imin, i - 1)
elif is_safe_ref(arr1, i) and is_safe_ref(arr2, j - 1) and arr1[i] < arr2[j - 1]:
return improve(i + 1, imax)
else:
return i, j
m, n = len(arr1), len(arr2)
return improve(0, m)
由于不能合并数组,这里用i
, j
标记左右的分界线。
取中心
def medium(arr1, arr2, i, j):
"""(max_of_left + min_of_right) // 2"""
m, n = len(arr1), len(arr2)
if i == 0:
max_of_left = arr2[j - 1]
elif j == 0:
max_of_left = arr1[i - 1]
else:
max_of_left = max(arr1[i - 1], arr2[j - 1])
if is_even(m + n):
if i == m:
min_of_right = arr2[j]
elif j == n:
min_of_right = arr1[i]
else:
min_of_right = min(arr1[i], arr2[j])
return (max_of_left + min_of_right) / 2
else:
return float(max_of_left)
多余元素划分到左侧组,两数组又不同时为空,所以无论总元素数是奇是偶,左侧组至少有一个元素。总元素数是偶数时,右侧组至少有一个元素。
如果允许既不属于左侧组又不属于右侧组的元素存在,就必须考虑“第三分组”的元素个数,以及“第三分组”何时存在等等问题,引入更多的复杂性。 ↩︎