📅  最后修改于: 2023-12-03 15:42:02.806000             🧑  作者: Mango
给定两个长度相同的数组 nums1 和 nums2,请你通过最多一次替换将两个数组中的相同索引元素的绝对差最小化,并返回最小化后的绝对差之和。
具体来说,就是求出 $\sum_{i=0}^{n-1}\left|nums1_i - nums2_i\right|$ 的最小值,其中 $n$ 是两个数组的长度。
要使得上述绝对差之和最小化,首先需要找到能够使差值最小化的数值对。两个数组中相同索引的元素必然是候选对之一,因此可以遍历一遍数组,求取相同索引元素的绝对差之和 $diff$,并记录下 $diff$ 变化的前后状态 $preDiff$ 和 $curDiff$。
假设在某次遍历中,处理到数组的第 $i$ 个元素,对应的 diff 变化前和变化后的值为 $preDiff$ 和 $curDiff$。那么,可以将两个数组中的某个元素替换为相同的数值,使得相同索引的元素之差最小化的情况,分为下面两种情况:
在两种情况中,取较小的一个变化量进行替换,即:
$$ \begin{aligned} curDiff &= \max(preDiff - (nums1_i - nums2_i), nums2_i - x + preDiff) \ &= preDiff + \min(nums1_i - nums2_i, nums2_i - x) \end{aligned} $$
因此,本题的解法就是逐步遍历两个数组,求取能够使得绝对差之和最小化的数值对,并计算出最小化后的绝对差之和。
def min_absolute_diff_sum(nums1: List[int], nums2: List[int]) -> int:
n = len(nums1)
diff = sum(abs(nums1[i] - nums2[i]) for i in range(n)) # 初始绝对差之和
for i in range(n):
preDiff, curDiff = diff, diff
# 情况1:修改 nums1 和 nums2 中同一索引的元素值
j = bisect_left(nums2, nums1[i])
if j < n:
curDiff = min(curDiff, preDiff - (nums1[i] - nums2[j]))
if j > 0:
curDiff = min(curDiff, preDiff - (nums2[j - 1] - nums1[i]))
# 情况2:只修改 nums1 中第 i 个元素的值
curDiff = min(curDiff, preDiff + nums1[i] - nums2[i])
diff = curDiff
return diff
本题的时间复杂度为 $O(n \log n)$,其中 $n$ 是数组的长度。主要的时间复杂度来自于两个二分查找,复杂度均为 $O(\log n)$。而空间复杂度为 $O(1)$,只需要常数空间用于存储 diff、preDiff 和 curDiff 等中间变量。