如何修改二分查找以返回有序数组中目标值的前后各两个最近元素?
嘿,这个需求其实很好实现——我们可以基于二分查找先定位目标值的插入位置,再从这个位置往前后抓取需要的元素就行!我给你一步步拆解清楚:
调整二分查找返回目标值的前后近邻元素
核心逻辑是:先找到目标值应该插入数组的位置(也就是第一个大于目标值的元素索引),这个位置就是后序元素的起点,前序元素则在它的左侧。之后我们只需要从这个位置出发,往左右各取最多2个元素(注意处理数组边界的特殊情况)。
具体步骤
- 第一步:用二分查找确定插入位置
和常规二分查找类似,但如果找不到目标值,我们要返回它应该插入的索引——也就是第一个比目标值大的元素位置。如果目标值比所有元素都大,就返回数组长度;比所有元素都小,返回0。 - 第二步:划定前后元素的范围
- 前序元素:从插入位置的前一位开始,往左最多取2个元素,要确保索引不小于0(避免越界)。
- 后序元素:从插入位置开始,往右最多取2个元素,确保索引不超过数组最后一位的索引。
- 第三步:收集并返回结果
把前序元素按从小到大的顺序,加上后序元素的顺序组合起来,就是最终需要的数组。
代码示例(Python实现)
def get_nearest_elements(arr, target): left, right = 0, len(arr) - 1 insert_pos = len(arr) # 默认插在数组末尾 # 二分查找定位插入位置 while left <= right: mid = (left + right) // 2 if arr[mid] == target: insert_pos = mid break elif arr[mid] < target: left = mid + 1 else: right = mid - 1 # 若未找到目标值,更新插入位置为left(此时left是第一个大于target的元素索引) if insert_pos == len(arr): insert_pos = left # 收集前序最多2个元素 prev_elements = [] # 起始索引:最多往前推2位,不能小于0 start_idx = max(0, insert_pos - 2) for i in range(start_idx, insert_pos): prev_elements.append(arr[i]) # 收集后序最多2个元素 next_elements = [] # 结束索引:最多往后推1位(因为从insert_pos开始取2个),不能超过数组最后一位 end_idx = min(len(arr) - 1, insert_pos + 1) for i in range(insert_pos, end_idx + 1): next_elements.append(arr[i]) # 合并前序和后序元素返回 return prev_elements + next_elements # 测试你的示例 test_arr = [101, 201, 301, 401, 501, 601, 701, 801, 901, 1001] target_val = 730 print(get_nearest_elements(test_arr, target_val)) # 输出: [601, 701, 801, 901]
边界情况处理说明
- 如果目标值比数组所有元素都小(比如
target=50),会返回前0个元素 + 前2个后序元素:[101, 201] - 如果目标值比数组所有元素都大(比如
target=1100),会返回最后2个前序元素 + 后0个元素:[901, 1001] - 如果目标值正好等于数组中的某个元素(比如
target=701),会返回该元素的前2个元素 + 该元素和后1个元素:[601, 701, 701, 801]——如果需要去重,可以在收集元素时额外判断,不过需求里没提这个,所以保留了原始逻辑。
内容的提问来源于stack exchange,提问作者thelaw




