返回
寻求正序数组的折中点:O(log(m+n)) 中位数算法
闲谈
2023-12-26 17:56:08
准备着手破解一道颇具挑战性的编程难题吧!想象你拥有两个正序排列的数组,也就是它们内里的数字已经按从小到大的顺序排列妥当。你的任务是找出这两个数组的“中位数”,也就是当把它们合并成一个数组时,正好处于中间位置的那个数字。
现在,事情变得棘手起来:我们要求你使用一种高效的算法,其时间复杂度为 O(log(m+n))。这可不是件容易的事,这意味着算法的运行时间不会随着数组长度的增加而呈指数级增长。
[算法的关键]
为了解决这个难题,我们采用“二分查找”的策略,巧妙地将问题化繁为简。我们先假设这两个数组已经合并成一个更大的数组,然后在这个假设的数组中执行二分查找,找出中位数。
-
找出合并数组的长度和中位数索引:
首先,计算合并数组的长度 m+n。然后,根据这个长度,确定中位数索引 mid,即 (m+n) // 2。
-
二分查找中位数:
现在,我们将对合并数组执行二分查找,不断缩小查找范围,直到找到中位数。
-
从头尾两个指针 low 和 high 开始,将它们分别初始化为 0 和 m+n-1。
-
找到中点索引 middle = (low + high) // 2,并计算其在合并数组中的位置:
- 如果 middle 落在 nums1 中,则位置为 left_part = middle。
- 如果 middle 落在 nums2 中,则位置为 right_part = middle - m。
-
检查 left_part 和 right_part 是否等于 mid:
- 如果相等,则 middle 就是中位数。
- 如果 left_part 小于 mid,则说明中位数在右侧,因此将 low 更新为 middle + 1。
- 如果 right_part 小于 mid,则说明中位数在左侧,因此将 high 更新为 middle - 1。
-
重复步骤 2,直到 low 和 high 相遇。
-
[代码示例]
为了加深理解,这里提供一个示例代码片段,用 Python 实现上述算法:
def find_median(nums1, nums2):
m, n = len(nums1), len(nums2)
low, high = 0, m + n - 1
while low <= high:
middle = (low + high) // 2
left_part = middle if middle < m else middle - m
right_part = middle - m if middle < m else middle
if left_part == right_part:
return nums1[left_part] if left_part < m else nums2[right_part]
elif left_part < right_part:
low = middle + 1
else:
high = middle - 1
raise ValueError("Invalid input arrays")
[扩展]
除了解决给定问题外,这种二分查找算法还有广泛的应用场景,如:
- 查找排序数组中的目标元素
- 查找有序列表中的特定元素
- 寻找序列中第一个大于或等于给定值的元素
只要你的问题涉及到在一个有序序列中高效地查找元素,二分查找都是一种强大的工具。掌握这种算法,解锁编程难题的新高度!