You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求解排序数组中外部目标值M的x个环绕值技术咨询

嘿,这个需求的核心其实是找到离目标值M最近的x个元素(x为偶数),并且返回排序后的结果对吧?结合你给的例子,我来拆解下高效实现的思路,步骤清晰且时间复杂度很低:

第一步:快速定位M的插入位置

因为数组是已排序且元素唯一的,用二分查找找插入位置是最优解,时间复杂度O(logn),比线性遍历高效得多。这个插入位置pos的定义是:数组中第一个大于M的元素的索引,它把数组分成了两部分——左边的元素都小于M,右边的都大于M。

比如你的例子:A = [2,3,5,8,10],M=4,二分查找会返回pos=2,也就是在3(索引1)和5(索引2)之间。

如果你用Python的话,可以直接用标准库的bisect.bisect_left函数,一行就能得到pos;如果是其他语言,自己实现二分查找也很简单,几行代码的事。

第二步:双指针选取最近的x个元素

接下来我们用双指针从插入点的左右两侧,每次选择离M更近的元素加入候选列表,直到选够x个:

  • 初始化左指针left = pos - 1(指向左侧最后一个小于M的元素),右指针right = pos(指向右侧第一个大于M的元素)。
  • 准备两个临时列表:left_elements(存从左侧选的元素)和right_elements(存从右侧选的元素)。
  • 循环x次:
    1. 如果左指针没有越界(left >= 0),并且要么右指针越界了,要么左侧元素离M的距离更小/相等:
      • 把A[left]加入left_elements,然后左指针左移一位(left -= 1)。
    2. 否则:
      • 把A[right]加入right_elements,然后右指针右移一位(right += 1)。

第三步:合并并返回排序后的结果

因为我们从左侧取元素是从近到远(也就是从大到小取的,比如例子里先取3,再取2),所以把left_elements反转一下,就变成了从小到大的顺序;而右侧的元素是从小到大取的(先取5,再取8),直接保留即可。最后把反转后的左侧列表和右侧列表合并,就是最终的升序结果。

比如你的例子:

  • x=2时:
    • 选左侧的3,右侧的5 → left_elements = [3],right_elements = [5]
    • 反转左侧得到[3],合并后是[3,5],符合要求。
  • x=4时:
    • 依次选3、5、2、8 → left_elements = [3,2],right_elements = [5,8]
    • 反转左侧得到[2,3],合并后是[2,3,5,8],完美匹配例子。

代码示例(Python)

import bisect

def find_surrounding_values(A, M, x):
    if not A or x < 1 or x > len(A) or x % 2 != 0:
        raise ValueError("Invalid input: x must be even between 1 and len(A)")
    
    pos = bisect.bisect_left(A, M)
    left = pos - 1
    right = pos
    left_elements = []
    right_elements = []
    
    for _ in range(x):
        if left >= 0 and (right >= len(A) or M - A[left] <= A[right] - M):
            left_elements.append(A[left])
            left -= 1
        else:
            right_elements.append(A[right])
            right += 1
    
    # 反转左侧元素得到升序,再和右侧合并
    return left_elements[::-1] + right_elements

# 测试例子
A = [2,3,5,8,10]
M = 4
print(find_surrounding_values(A, M, 2))  # 输出 [3,5]
print(find_surrounding_values(A, M, 4))  # 输出 [2,3,5,8]

时间复杂度分析

  • 二分查找:O(logn)
  • 双指针选取元素:O(x)
  • 反转和合并:O(x)
    整体时间复杂度是O(logn + x),对于n较大的数组非常高效,因为x最多是n,最坏情况是O(n),但比直接遍历整个数组找最近元素要优得多。

另外,这个逻辑还能处理M在数组两端的情况,比如M=1(插入点0),x=2时会返回[2,3];M=11(插入点5),x=2时返回[8,10],完全符合“环绕值”的需求。

内容的提问来源于stack exchange,提问作者rubyquartz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:34:08