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

如何高效实现带半径r的数组重排算法:避免元素近邻冲突

高效解决数组重排满足半径约束问题

问题核心

要求重排数组,使得任意相邻元素的绝对值差 > r;若无法完全满足,返回满足该约束的元素数量最多的数组。

高效解法思路

1. 先排序,再分半穿插放置

这是最容易实现且效率最高的策略,时间复杂度为O(n log n)(主要来自排序),适用于大多数场景:

  • 步骤1:排序数组:将原数组按升序排序,让值相近的元素集中,方便后续间隔放置。
  • 步骤2:分半穿插:
    • 将排序后的数组分为前半段(arr[0:mid])和后半段(arr[mid:]),其中mid = len(arr) // 2。
    • 交替从后半段、前半段取元素构建结果数组;若其中一段先取完,直接追加剩余段的元素。
    • 例如输入[1,2,3,4,5,6],r=2:
      排序后为原数组,mid=3,后半段是[4,5,6],前半段是[1,2,3],穿插后得到[4,1,5,2,6,3],所有相邻元素差均为3或4,满足>2的约束。

2. 处理无法完全满足的情况

如果穿插后的数组存在相邻元素差≤r的情况(比如大量重复元素或值密集的数组),需要做局部调整或裁剪:

  • 遍历验证与裁剪:遍历结果数组,若发现相邻元素不满足约束,移除其中一个元素(优先移除重复次数较多的元素,或者后续可替换空间更小的元素),直到所有相邻元素都满足约束,或无法再裁剪。
  • 重复元素特殊处理:若数组中有多个相同值的元素,由于相同值的元素相邻必然不满足约束(差为0≤r),需要用其他元素隔开。如果没有足够的间隔元素,只能保留尽可能多的相同元素,每两个相同元素之间至少间隔一个符合条件的元素。

3. 贪心选最大间隔(适用于复杂场景)

当分半穿插无法得到最优解时,可以用优先队列(堆)实现贪心策略,每次选择与最后放入元素差值最大的候选元素,最大化后续放置的可能性:

  • 统计每个元素的出现次数,存入哈希表。
  • 将所有元素放入大顶堆(按值排序)。
  • 初始化结果数组,先取出堆顶元素放入,然后循环:
    • 从堆中取出与最后一个元素差值>r的元素,放入结果数组,减少该元素的计数,若计数>0则放回堆。
    • 若没有符合条件的元素,取出堆顶元素(即使差值≤r),此时只能放弃该元素(不放入结果),直到堆为空。

示例代码(分半穿插实现)

def rearrange_array(arr, r):
    arr.sort()
    n = len(arr)
    mid = n // 2
    res = []
    i, j = mid, 0
    # 先穿插后半段和前半段
    while i < n and j < mid:
        res.append(arr[i])
        res.append(arr[j])
        i += 1
        j += 1
    # 追加剩余元素
    while i < n:
        res.append(arr[i])
        i += 1
    while j < mid:
        res.append(arr[j])
        j += 1
    
    # 验证并裁剪不满足条件的相邻元素
    k = 1
    while k < len(res):
        if abs(res[k] - res[k-1]) <= r:
            # 移除当前元素,也可以选择移除前一个,这里优先移除当前
            res.pop(k)
        else:
            k += 1
    return res

说明

  • 分半穿插的思路利用了排序后前后半段元素值差距较大的特点,大概率能满足相邻差>r的约束,且实现简单高效。
  • 验证裁剪步骤确保最终数组满足约束,同时尽可能保留最多元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:06:10