数组重排最小化差值 | 豆包MarsCode AI刷题

223 阅读4分钟

为了解决这个问题,我们需要最小化 sum(abs(a[i] - b[i])),其中 ab 是两个数组,我们可以重新排列 a 的元素,以实现最小化的目标。

关键观察:

  • 我们要最小化 sum(abs(a[i] - b[i])),即数组 ab 对应位置元素的差的绝对值之和。
  • 为了最小化这种差异,每个 a[i]b[i] 的差值越小越好。这意味着我们可以通过适当的排列,使得 a[i]b[i] 的差尽量小。
  • 一个简单的有效策略是:将数组 a 和数组 b 都排序,然后对应位置的元素相减。为什么呢?
    • 当两个数组都排序时,最小的元素对应最小的元素,中等的元素对应中等的元素,最大元素对应最大元素,这样能最大程度减少大差异。

解题步骤:

  1. 排序:先对 ab 都进行排序。
  2. 计算差异:遍历排序后的 ab,计算 sum(abs(a[i] - b[i]))

代码实现:

def solution(a: list, b: list) -> int:
    # Step 1: 对两个数组排序
    a.sort()
    b.sort()
    
    # Step 2: 计算元素差异的绝对值之和
    total_diff = 0
    for i in range(len(a)):
        total_diff += abs(a[i] - b[i])
    
    # Step 3: 返回结果
    return total_diff

# 测试
if __name__ == '__main__':
    print(solution([2, 1, 3, 2], [5, 2, 4, 2]) == 5)  # 输出:5
    print(solution([1, 4, 6], [2, 5, 7]) == 3)        # 输出:3
    print(solution([1, 9, 6], [2, 5, 7]) == 4)        # 输出:4

解释:

  1. 排序:通过对数组 ab 进行排序,确保两个数组的元素分别处于递增顺序。
  2. 计算差值:遍历两个排序后的数组 ab,对每一对对应元素计算它们的差的绝对值,并将这些差的绝对值相加。
  3. 返回结果:返回差的总和,即我们要最小化的目标值。

复杂度分析:

  • 排序的时间复杂度是 O(n log n),其中 n 是数组的长度。
  • 计算差异的时间复杂度是 O(n),因此总的时间复杂度是 O(n log n)。

测试用例分析:

  1. 测试用例 1
    • 输入:a = [2, 1, 3, 2], b = [5, 2, 4, 2]
    • 排序后:a = [1, 2, 2, 3], b = [2, 2, 4, 5]
    • 差异:abs(1-2) + abs(2-2) + abs(2-4) + abs(3-5) = 1 + 0 + 2 + 2 = 5
    • 结果:5
  2. 测试用例 2
    • 输入:a = [1, 4, 6], b = [2, 5, 7]
    • 排序后:a = [1, 4, 6], b = [2, 5, 7]
    • 差异:abs(1-2) + abs(4-5) + abs(6-7) = 1 + 1 + 1 = 3
    • 结果:3
  3. 测试用例 3
    • 输入:a = [1, 9, 6], b = [2, 5, 7]
    • 排序后:a = [1, 6, 9], b = [2, 5, 7]
    • 差异:abs(1-2) + abs(6-5) + abs(9-7) = 1 + 1 + 2 = 4
    • 结果:4

通过这种方法,我们可以保证最小化差异并得到正确的结果。

总结

这个问题涉及到的核心概念主要有排序和最优化,并且与贪心算法有关系。下面我将补充一些相关的知识背景,帮助更好地理解和拓展这类问题。

  1. 排序与优化 排序是许多算法中的基础步骤,特别是在需要比较元素之间的关系时。通过排序,我们能够确保某些类型的最优解的结构。这里,我们通过对数组 a 和 b 进行排序,使得在相同位置上的元素尽可能接近,从而最小化它们的差异。

排序的性质 升序和降序排序:升序排序(从小到大)是一个基础的操作,常用于需要最小化差异的场景。例如,sum(abs(a[i] - b[i])) 可以通过将两个数组排序后直接对应最小化差异。 稳定性:排序算法的稳定性是指,当多个元素的值相等时,它们在排序后的相对顺序不发生改变。对于本问题来说,即使 a[i] 和 b[i] 有相同的值,排序后它们的相对位置不变,确保了不需要担心相同元素之间的顺序问题。 2. 贪心算法(Greedy Algorithm) 贪心算法的基本思想是:在每一步选择中,采取当前状态下最优的选择,而不考虑后续的影响。对于本问题,我们通过以下贪心策略来最小化差异:

贪心策略:通过将 a 和 b 分别排序,然后逐对对应元素进行比较,这样能保证每一对元素的差值是最小的。 为什么是贪心策略:排序后,每个 a[i] 对应一个最接近它的 b[i],从而最小化了每个元素之间的差值。这个选择不会影响其他的元素,因此是局部最优的选择,也是全局最优的解。 贪心算法的一般步骤: