一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。
给你一个整数数组 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
又是看的一知半解的一天,为什么“每次加上(2k)*第k小值,减去(2k)*第k大值”没看懂,前面的这么加起来倒是想到了
接下来考虑如何用代码计算。直接写是不可能的,因为不可能算2100000,所以我们维护一个系数,从1到2(n-1),每次乘二,根据上述的描述,可以推知,以第k小元素为最大值的序列数=以第k大元素为最小值的序列数=2k,(k从0开始),所以我们从小到大遍历,每次加上(2k)*第k小值,减去(2^k)*第k大值。
class Solution {
public int sumSubseqWidths(int[] nums) {
Arrays.sort(nums);
long k = 1;
long ans = 0;
final int MOD = 1000000007;
int len = nums.length;
for (int i = 0; i < len; i++) {
ans = (ans + nums[i] * k - nums[len - 1 - i] * k) % MOD;
k = (k * 2) % MOD;
}
return (int) ((ans + MOD) % MOD);
}
}