📅  最后修改于: 2023-12-03 15:39:10.001000             🧑  作者: Mango
在算法竞赛中,对于一组数,经常需要求解其两两之间的差的绝对值的和,即对于给定的序列$a_1,a_2,a_3,……,a_n$,需要求解表达式$\sum\limits_{i=1}^n\sum\limits_{j=1}^n|a_i-a_j|$的值。
本题需要求解的是,对于给定的序列$a_1,a_2,a_3,……,a_n$,需要求解表达式$\max\limits_{x=1}^n\min\limits_{y=1}^n|a_x-a_y|$和$\sum\limits_{i=1}^n\sum\limits_{j=1}^n|a_i-a_j|$。
对于求解$\max\limits_{x=1}^n\min\limits_{y=1}^n|a_x-a_y|$,可以通过二分查找的方式进行求解。具体地,对于二分的中间值mid,判断序列中是否有一对数的差的绝对值大于mid,如果没有,则将mid减一继续检查。
对于求解$\sum\limits_{i=1}^n\sum\limits_{j=1}^n|a_i-a_j|$,可以将其转化为$\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n(|a_i-a_j|+|a_j-a_i|)$的形式,即$\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n2|a_i-a_j|$,再用双重循环计算即可。
def min_max_sum(a: List[int]) -> Tuple[int, int]:
n = len(a)
start, end = 0, max(a) - min(a)
while start < end:
mid = (start + end) // 2
if not any(abs(a[i] - a[j]) > mid for i in range(n) for j in range(n)):
end = mid
else:
start = mid + 1
min_sum = 0
for i in range(n):
for j in range(i + 1, n):
min_sum += abs(a[i] - a[j])
max_sum = max(abs(a[i] - a[j]) for i in range(n) for j in range(n))
return min_sum, max_sum
时间复杂度:$\mathcal{O}(n^2\log W)$,其中$W$为$a$数组中的最大值和最小值之差。
空间复杂度:$\mathcal{O}(1)$。
该问题的解法比较直观,但是需要仔细思考推导出对应的解法。需要注意的是,在计算$\max\limits_{x=1}^n\min\limits_{y=1}^n|a_x-a_y|$时,需要用到二分查找,此时需要判断序列中是否有一对数的差的绝对值大于mid这一点。