📅  最后修改于: 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),需要统计每个数出现的次数。