1、题干
一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。
给你一个整数数组 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
Problem: 891. 子序列宽度之和
2、思路
还得是按官解的排序+计算贡献值的思路去做:
- 对长度为
n
的整数数组nums
升序排列 - 数组
nums
中第i
个整数贡献的最小值次数是: - 数组
nums
中第i
个整数贡献的最大值次数是: - 累计每个元素的贡献值
计算贡献次数实际是计算组合数:
由于数据过大需要取余,第一版用快速幂实现,居然只通过了 20+ 个用例,真是裂开了😳;把快速幂改成打表后过了。。。
3、Code
function sumSubseqWidths(nums: number[]): number {
const n = nums.length, MOD = 1e9 + 7;
nums.sort((a, b) => a - b);
const pow = new Array(n).fill(1);
for (let i = 1; i < n; i++) pow[i] = 2 * pow[i - 1] % MOD;
let res = 0;
for (let i = 0; i < n; i++) {
res = (res + nums[i] * (pow[i] - pow[n - i - 1])) % MOD;
}
return res;
};
4、复杂度
- 时间复杂度:
- 空间复杂度: