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

严格增减数组求A[i]-B[i]最小绝对差索引及算法优化咨询

解决方案:利用单调性实现无浮点的二分查找

首先明确问题核心性质:假设A严格递增、B严格递减,构造序列 C[i] = A[i] - B[i],由于A递增、-B也递增,因此C是严格递增序列。而|C[i]|的最小值要么出现在C[i]由负转正的转折点,要么在序列两端(当C全正或全负时)。基于这个性质,我们可以用二分查找实现O(log n)复杂度的解法,完全避免浮点运算,逻辑更简洁。

具体实现代码

def find_min_abs_index(A, B):
    n = len(A)
    if n == 0:
        return -1  # 空序列边界处理
    left, right = 0, n - 1
    
    # 二分查找第一个C[i] >= 0的位置
    while left < right:
        mid = (left + right) // 2
        if A[mid] - B[mid] < 0:
            left = mid + 1
        else:
            right = mid
    
    # 筛选可能的候选位置:临界点、前一个位置、两端(全正/全负情况)
    candidates = [(abs(A[left] - B[left]), left)]
    if left > 0:
        candidates.append((abs(A[left-1] - B[left-1]), left-1))
    # 处理全负情况
    if A[0] - B[0] < 0 and left == 0:
        candidates.append((abs(A[-1] - B[-1]), n-1))
    # 处理全正情况
    elif A[-1] - B[-1] > 0 and left == n-1:
        candidates.append((abs(A[0] - B[0]), 0))
    
    # 按绝对值升序、索引升序排序,取第一个结果
    candidates.sort(key=lambda x: (x[0], x[1]))
    return candidates[0][1]

代码说明

  1. 二分查找逻辑:通过整数运算比较A[mid] - B[mid]的正负,快速定位C序列由负转正的临界点,无浮点误差。
  2. 候选位置筛选:最小值只会出现在临界点、临界点前一个位置,或序列两端(全正/全负场景),无需遍历所有元素。
  3. 结果选择:对候选位置按「绝对值最小优先,索引最小次之」排序,直接得到符合要求的答案。

对比黄金分割法的优势

  • 完全避免浮点运算,不存在round带来的索引计算误差,逻辑更可靠。
  • 代码更简洁,无需处理黄金分割法后续的邻域检查逻辑。
  • 二分查找的常数因子更小,实际运行效率更高。

原黄金分割法的改进思路(可选)

如果一定要保留黄金分割思路,可以用斐波那契数列代替浮点比例计算(黄金分割的近似值可由斐波那契数的比值逼近),实现整数版本的黄金分割搜索:

def fibonacci_search(A, B):
    def f(x):
        return abs(A[x] - B[x])
    n = len(A)
    # 找到大于等于n的最小斐波那契数对
    fib_k, fib_k1 = 1, 0
    while fib_k < n:
        fib_k, fib_k1 = fib_k + fib_k1, fib_k
    offset = -1
    while fib_k > 1:
        i = min(offset + fib_k1, n-1)
        if f(i) > f(offset + fib_k):
            fib_k = fib_k1
            fib_k1 = fib_k - fib_k1
            offset = i
        else:
            fib_k = fib_k1
            fib_k1 = fib_k - fib_k1
    # 筛选最后几个候选位置
    candidates = [offset+1]
    if offset >= 0:
        candidates.append(offset)
    if offset + 2 < n:
        candidates.append(offset+2)
    # 找到最优索引
    min_val = float('inf')
    min_idx = 0
    for idx in candidates:
        val = f(idx)
        if val < min_val or (val == min_val and idx < min_idx):
            min_val = val
            min_idx = idx
    return min_idx

不过这种方法逻辑复杂度高于二分查找,仅适合需要黄金分割的特定场景。

验证代码

用你提供的测试逻辑验证:

import random

def make_arr(inv):
    x = set()
    while len(x) != 1000:
        x.add(random.randint(-10000,10000))
    x = sorted(list(x), reverse=inv)
    return x

x = make_arr(0)
y = make_arr(1)
# 暴力求解正确答案
needle = float('inf')
c = 0
for i in range(1000):
    current = abs(x[i]-y[i])
    if current < needle or (current == needle and i < c):
        c = i
        needle = current
print("暴力求解结果:", c)
print("二分查找结果:", find_min_abs_index(x, y))
print("斐波那契搜索结果:", fibonacci_search(x, y))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 19:01:28