📜  给定数组中所有对的绝对差之和(1)

📅  最后修改于: 2023-12-03 14:56:54.291000             🧑  作者: Mango

给定数组中所有对的绝对差之和

题目描述

给定一个整数数组,求出数组中所有数对的绝对差之和。

示例

输入: [1, 4, 2, 8] 输出: 26 解释: 所有数对的绝对差之和为:|1-4| + |1-2| + |1-8| + |4-2| + |4-8| + |2-8| = 26。

解法

对于一个整数数组,可以枚举其所有数对进行计算,但这样的时间复杂度为O(N^2)。可以利用以下的规律来降低时间复杂度。

对于数组中的任意两个数A和B,其绝对差为|A-B|。当数组中的数按升序排列后,对于任意一个数A,在其左边的B都小于等于A,而在其右边的B都大于等于A,因此对于任意一个数A,其左边的数对绝对差为A与左边所有数的差的绝对值之和,而其右边的数对绝对差为A与右边所有数的差的绝对值之和。因此,我们不必求出所有数对的绝对差之和,只需要求出每个数对的贡献,再将其求和即可。

对于一个数对A和B,其绝对差为|A-B|,其贡献为|A-B|*出现次数。在已知数组中的数对出现次数的情况下,可以用以下的代码求出所有数对的绝对差之和。

def absolute_difference_sum(nums: List[int]) -> int:
    nums.sort()
    res = 0
    
    # 统计每个数出现的次数
    cnt = collections.Counter(nums)
    
    # 计算左边的数对绝对差之和
    left_sum = 0
    pre = nums[0]
    for i in range(1, len(nums)):
        left_sum += i*(nums[i]-pre)
        pre = nums[i]
    
    # 计算右边的数对绝对差之和
    right_sum = 0
    pre = nums[-1]
    for i in range(len(nums)-2, -1, -1):
        right_sum += (len(nums)-i-1)*(pre-nums[i])
        pre = nums[i]
    
    return left_sum+right_sum
复杂度分析

时间复杂度:O(NlogN),其中N为数组的长度,排序的复杂度为O(NlogN),求左右两侧数对绝对差贡献的复杂度为O(N)。

空间复杂度:O(N),需要统计每个数出现的次数。