一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。
给你一个整数数组 nums
,返回 nums
的所有非空 子序列 的 宽度之和 。由于答案可能非常大,请返回对 109 + 7
取余 后的结果。
子序列 定义为从一个数组里删除一些(或者不删除)元素,但不改变剩下元素的顺序得到的数组。例如,[3,6,2,7]
就是数组[0,3,1,6,2,2,7]
的一个子序列。
示例 1:
**输入:** nums = [2,1,3]
**输出:** 6
**解释:** 子序列为 [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3] 。
相应的宽度是 0, 0, 0, 1, 1, 2, 2 。
宽度之和是 6 。
示例 2:
**输入:** nums = [2]
**输出:** 0
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 105
方法一:数学 根据子序列的定义,我们可以知道数组元素的顺序对最终结果无影响,因此我们首先对数组从小到大进行排序。对于两个元素 nums}[i] 和 nums}[j],其中 i \lt j,以 nums}[i] 和 nums}[j] 为最小值和最大值的子序列数目(两个元素相等时,我们以下标大小判断元素大小)为 2^{j-i-1。那么所有以 nums}[j] 为最大值的子序列宽度之和为(长度为 1 的子序列对结果无影响):
\begin{aligned} B_j &= \sum_{i \lt j} {(\textit{nums}[j] - \textit{nums}[i]) \times 2^{j-i-1}} \ &= \sum_{i \lt j}{\textit{nums}[j] \times 2^{j-i-1}} - \sum_{i \lt j}{\textit{nums}[i] \times 2^{j-i-1}} \ &= \textit{nums}[j] \times (2^j - 1) - \sum_{i \lt j}{\textit{nums}[i] \times 2^{j-i-1}} \end{aligned}
记 x_j = \sum_{i \lt j}{\textit{nums}[i] \times 2^{j-i-1},那么:
\begin{aligned} x_{j+1} &= \sum_{i \lt j+1}{\textit{nums}[i] \times 2^{j-i}} \ &= \sum_{i \lt j}{\textit{nums}[i] \times 2^{j-i}} + \textit{nums}[j] \ &= 2 \times x_j + \textit{nums}[j] \end{aligned}
因此 B_{j+1 的结果可以利用计算 B_j 时的部分数据来计算,记 y_j = 2^j,那么 B_j=\textit{nums}[j] \times (y_j-1) - x_j,B_{j+1}=\textit{nums}[j+1] \times (y_{j+1}-1) - x_{j+1,由上面的推导可知 y_{j+1}=2 \times y_j,x_{j+1}=2\times x_j + \textit{nums}[j]。所有子序列的宽度之和就是所有 B_j 的和。
[sol1-Python3] 1 2 3 4 5 6 7 8 9 10 11 class Solution : def sumSubseqWidths (self, nums: List [int ] ) -> int : nums.sort() res = 0 MOD = 10 ** 9 + 7 x, y = nums[0 ], 2 for j in range (1 , len (nums)): res = (res + nums[j] * (y - 1 ) - x) % MOD x = (x * 2 + nums[j]) % MOD y = y * 2 % MOD return (res + MOD) % MOD
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution {public : int sumSubseqWidths (vector<int >& nums) { sort (nums.begin (), nums.end ()); long long res = 0 , mod = 1e9 + 7 ; long long x = nums[0 ], y = 2 ; for (int j = 1 ; j < nums.size (); j++) { res = (res + nums[j] * (y - 1 ) - x) % mod; x = (x * 2 + nums[j]) % mod; y = y * 2 % mod; } return (res + mod) % mod; } };
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int sumSubseqWidths (int [] nums) { final int MOD = 1000000007 ; Arrays.sort(nums); long res = 0 ; long x = nums[0 ], y = 2 ; for (int j = 1 ; j < nums.length; j++) { res = (res + nums[j] * (y - 1 ) - x) % MOD; x = (x * 2 + nums[j]) % MOD; y = y * 2 % MOD; } return (int ) ((res + MOD) % MOD); } }
[sol1-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Solution { public int SumSubseqWidths (int [] nums ) { const int MOD = 1000000007 ; Array.Sort(nums); long res = 0 ; long x = nums[0 ], y = 2 ; for (int j = 1 ; j < nums.Length; j++) { res = (res + nums[j] * (y - 1 ) - x) % MOD; x = (x * 2 + nums[j]) % MOD; y = y * 2 % MOD; } return (int ) ((res + MOD) % MOD); } }
[sol1-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static int cmp (const void *pa, const void *pb) { return *(int *)pa - *(int *)pb; } int sumSubseqWidths (int * nums, int numsSize) { qsort(nums, numsSize, sizeof (int ), cmp); long long res = 0 , mod = 1e9 + 7 ; long long x = nums[0 ], y = 2 ; for (int j = 1 ; j < numsSize; j++) { res = (res + nums[j] * (y - 1 ) - x) % mod; x = (x * 2 + nums[j]) % mod; y = y * 2 % mod; } return (res + mod) % mod; }
[sol1-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 var sumSubseqWidths = function (nums ) { const MOD = 1000000007 ; nums.sort ((a, b ) => a - b); let res = 0 ; let x = nums[0 ], y = 2 ; for (let j = 1 ; j < nums.length ; j++) { res = (res + nums[j] * (y - 1 ) - x) % MOD ; x = (x * 2 + nums[j]) % MOD ; y = y * 2 % MOD ; } return (res + MOD ) % MOD ; };
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 func sumSubseqWidths (nums []int ) int { const mod int = 1e9 + 7 sort.Ints(nums) res, x, y := 0 , nums[0 ], 2 for _, num := range nums[1 :] { res = (res + num*(y-1 ) - x) % mod x = (x*2 + num) % mod y = y * 2 % mod } return (res + mod) % mod }
复杂度分析