题目
标题和出处
标题:有序数组中差绝对值之和
难度
6 级
题目描述
要求
给定一个非递减有序整数数组 nums \texttt{nums} nums。
建立并返回一个整数数组 result \texttt{result} result,要求和 nums \texttt{nums} nums 长度相同,且 result[i] \texttt{result[i]} result[i] 等于 nums[i] \texttt{nums[i]} nums[i] 与数组中所有其他元素差的绝对值之和。
换言之, result[i] \texttt{result[i]} result[i] 等于 sum(|nums[i]-nums[j]|) \texttt{sum(|nums[i]-nums[j]|)} sum(|nums[i]-nums[j]|),其中 0 ≤ j < nums.length \texttt{0} \le \texttt{j} < \texttt{nums.length} 0≤j<nums.length 且 j ≠ i \texttt{j} \ne \texttt{i} j=i(下标从 0 \texttt{0} 0 开始)。
示例
示例 1:
输入: nums = [2,3,5] \texttt{nums = [2,3,5]} nums = [2,3,5]
输出: [4,3,5] \texttt{[4,3,5]} [4,3,5]
解释:假设数组下标从 0 \texttt{0} 0 开始,那么
result[0] = |2-2| + |2-3| + |2-5| = 0 + 1 + 3 = 4 \texttt{result[0] = |2-2| + |2-3| + |2-5| = 0 + 1 + 3 = 4} result[0] = |2-2| + |2-3| + |2-5| = 0 + 1 + 3 = 4,
result[1] = |3-2| + |3-3| + |3-5| = 1 + 0 + 2 = 3 \texttt{result[1] = |3-2| + |3-3| + |3-5| = 1 + 0 + 2 = 3} result[1] = |3-2| + |3-3| + |3-5| = 1 + 0 + 2 = 3,
result[2] = |5-2| + |5-3| + |5-5| = 3 + 2 + 0 = 5 \texttt{result[2] = |5-2| + |5-3| + |5-5| = 3 + 2 + 0 = 5} result[2] = |5-2| + |5-3| + |5-5| = 3 + 2 + 0 = 5。
示例 2:
输入: nums = [1,4,6,8,10] \texttt{nums = [1,4,6,8,10]} nums = [1,4,6,8,10]
输出: [24,15,13,15,21] \texttt{[24,15,13,15,21]} [24,15,13,15,21]
数据范围
- 2 ≤ nums.length ≤ 10 5 \texttt{2} \le \texttt{nums.length} \le \texttt{10}^\texttt{5} 2≤nums.length≤105
- 1 ≤ nums[i] ≤ nums[i + 1] ≤ 10 4 \texttt{1} \le \texttt{nums[i]} \le \texttt{nums[i + 1]} \le \texttt{10}^\texttt{4} 1≤nums[i]≤nums[i + 1]≤104
解法
思路和算法
由于数组 nums \textit{nums} nums 按非递减顺序排序,因此数组中的任意两个元素的差的绝对值等于后面的元素减前面的元素(即下标大的元素减下标小的元素)。当计算 result [ i ] \textit{result}[i] result[i] 时,对于每个下标 j j j,当 j < i j < i j<i 时将 nums [ i ] − nums [ j ] \textit{nums}[i] - \textit{nums}[j] nums[i]−nums[j] 加到 result [ i ] \textit{result}[i] result[i],当 j > i j > i j>i 时将 nums [ j ] − nums [ i ] \textit{nums}[j] - \textit{nums}[i] nums[j]−nums[i] 加到 result [ i ] \textit{result}[i] result[i]。
当 j = i j = i j=i 时, nums [ j ] − nums [ i ] = 0 \textit{nums}[j] - \textit{nums}[i] = 0 nums[j]−nums[i]=0,将 nums [ j ] − nums [ i ] \textit{nums}[j] - \textit{nums}[i] nums[j]−nums[i] 加到 result [ i ] \textit{result}[i] result[i] 不会影响结果。为了方便处理, j = i j = i j=i 的情况与 j > i j > i j>i 的情况可以合并,即当 j ≥ i j \ge i j≥i 时将 nums [ j ] − nums [ i ] \textit{nums}[j] - \textit{nums}[i] nums[j]−nums[i] 加到 result [ i ] \textit{result}[i] result[i]。
用 n n n 表示数组 nums \textit{nums} nums 的长度,则 result [ i ] \textit{result}[i] result[i] 计算如下:
result [ i ] = ∑ j = 0 i − 1 ( nums [ i ] − nums [ j ] ) + ∑ j = i n − 1 ( nums [ j ] − nums [ i ] ) = ( ∑ j = i n − 1 nums [ j ] − ∑ j = 0 i − 1 nums [ j ] ) + ( ∑ j = 0 i − 1 nums [ i ] − ∑ j = i n − 1 nums [ i ] ) = ( ∑ j = i n − 1 nums [ j ] − ∑ j = 0 i − 1 nums [ j ] ) + nums [ i ] × ( 2 × i − n ) \begin{aligned} &\textit{result}[i] \\ = &\sum\limits_{j = 0}^{i - 1} (\textit{nums}[i] - \textit{nums}[j]) + \sum\limits_{j = i}^{n - 1} (\textit{nums}[j] - \textit{nums}[i]) \\ = &(\sum\limits_{j = i}^{n - 1} \textit{nums}[j] - \sum\limits_{j = 0}^{i - 1} \textit{nums}[j]) + (\sum\limits_{j = 0}^{i - 1} \textit{nums}[i] - \sum\limits_{j = i}^{n - 1} \textit{nums}[i]) \\ = &(\sum\limits_{j = i}^{n - 1} \textit{nums}[j] - \sum\limits_{j = 0}^{i - 1} \textit{nums}[j]) + \textit{nums}[i] \times (2 \times i - n) \end{aligned} ===result[i]j=0∑i−1(nums[i]−nums[j])+j=i∑n−1(nums[j]−nums[i])(j=i∑n−1nums[j]−j=0∑i−1nums[j])+(j=0∑i−1nums[i]−j=i∑n−1nums[i])(j=i∑n−1nums[j]−j=0∑i−1nums[j])+nums[i]×(2×i−n)
令 leftSum [ i ] = ∑ j = 0 i − 1 nums [ j ] \textit{leftSum}[i] = \sum\limits_{j = 0}^{i - 1} \textit{nums}[j] leftSum[i]=j=0∑i−1nums[j], rightSum [ i ] = ∑ j = i n − 1 nums [ j ] \textit{rightSum}[i] = \sum\limits_{j = i}^{n - 1} \textit{nums}[j] rightSum[i]=j=i∑n−1nums[j],则有 result [ i ] = ( rightSum [ i ] − leftSum [ i ] ) + nums [ i ] × ( 2 × i − n ) \textit{result}[i] = (\textit{rightSum}[i] - \textit{leftSum}[i]) + \textit{nums}[i] \times (2 \times i - n) result[i]=(rightSum[i]−leftSum[i])+nums[i]×(2×i−n)。其中, leftSum [ i ] \textit{leftSum}[i] leftSum[i] 为数组 nums \textit{nums} nums 的前 i i i 个元素的前缀和, rightSum [ i ] \textit{rightSum}[i] rightSum[i] 为数组 nums \textit{nums} nums 的后 n − i n - i n−i 个元素之和,可以在遍历数组 nums \textit{nums} nums 的过程中计算 leftSum [ i ] \textit{leftSum}[i] leftSum[i] 和 rightSum [ i ] \textit{rightSum}[i] rightSum[i] 的值。
实现方面,可以维护两个变量 leftSum \textit{leftSum} leftSum 和 rightSum \textit{rightSum} rightSum,初始时 leftSum = 0 \textit{leftSum} = 0 leftSum=0, rightSum \textit{rightSum} rightSum 为数组 nums \textit{nums} nums 的全部元素之和,在遍历数组 nums \textit{nums} nums 的过程中更新两个变量的值。
从左到右遍历数组 nums \textit{nums} nums,对于下标 i i i,执行如下操作。
计算 result [ i ] = ( rightSum − leftSum ) + nums × ( 2 × i − n ) \textit{result}[i] = (\textit{rightSum} - \textit{leftSum}) + \textit{nums} \times (2 \times i - n) result[i]=(rightSum−leftSum)+nums×(2×i−n)。
将 leftSum \textit{leftSum} leftSum 增加 nums [ i ] \textit{nums}[i] nums[i],将 rightSum \textit{rightSum} rightSum 减少 nums [ i ] \textit{nums}[i] nums[i]。
遍历结束之后即可得到结果数组 result \textit{result} result。
代码
class Solution {
public int[] getSumAbsoluteDifferences(int[] nums) {
int n = nums.length;
int[] result = new int[n];
int leftSum = 0, rightSum = 0;
for (int i = 0; i < n; i++) {
rightSum += nums[i];
}
for (int i = 0; i < n; i++) {
result[i] = rightSum - leftSum + nums[i] * (2 * i - n);
leftSum += nums[i];
rightSum -= nums[i];
}
return result;
}
}
复杂度分析
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。计算前缀和与计算答案数组各需要遍历数组 nums \textit{nums} nums 一次。
空间复杂度: O ( 1 ) O(1) O(1)。注意返回值不计入空间复杂度。