📅  最后修改于: 2023-12-03 15:42:10.347000             🧑  作者: Mango
给定两个有序数组a1和a2,大小分别为n和m。设计一个O(log n + log m)时间复杂度的算法,找出这两个数组合并后的中位数。
首先,根据求中位数的性质,我们可以将问题转化为求第k小的数,其中k为两个数组长度之和的中位数。
然后,我们可以通过二分查找的方式进行求解。具体来说,我们先取两个数组各自的中位数,将它们合并成一个有序数组。接着,如果这个有序数组的长度为奇数,我们可以直接返回中间的数;如果是偶数,则我们需要返回中间两个数的平均数。
如果这个中位数的值大于等于k,那么我们需要在两个数组各自的左半部分中查找,反之则在右半部分中查找。在查找时,我们可以比较两个数组所有左半部分的最大值和右半部分的最小值,来判断应该插入哪一半。
最后,当我们在一个数组中找到了第k小的数,那么我们只需要将它和另一个数组对应位置上的数进行比较,即可得到合并后的第k小的数。
def find_median_sorted_arrays(nums1, nums2):
n = len(nums1)
m = len(nums2)
if n > m:
nums1, nums2, n, m = nums2, nums1, m, n
if m == 0:
raise ValueError
median_idx = (n + m - 1) // 2
lidx, ridx = 0, n
while lidx < ridx:
i = (lidx + ridx) // 2
j = median_idx - i
if i < n and nums2[j-1] > nums1[i]:
lidx = i + 1
elif i > 0 and nums1[i-1] > nums2[j]:
ridx = i - 1
else:
break
if i == n:
med_right = nums2[j]
elif j == m:
med_right = nums1[i]
else:
med_right = min(nums1[i], nums2[j])
if (n + m) % 2 == 1:
return med_right
if i == 0:
med_left = nums2[j-1]
elif j == 0:
med_left = nums1[i-1]
else:
med_left = max(nums1[i-1], nums2[j-1])
return (med_left + med_right) / 2
我们使用二分查找的方式,将搜索空间每次缩小一半,因此时间复杂度为$O(log(n) + log(m))$。而由于我们只使用了常数级别的额外空间,因此空间复杂度为$O(1)$。