📌  相关文章
📜  对的绝对差的最小和最大和(1)

📅  最后修改于: 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这一点。