LC891. 子序列宽度之和题解
题目来源LC891. 子序列宽度之和
题干
一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。
给你一个整数数组 nums ,返回 nums 的所有非空 子序列 的 宽度之和 。由于答案可能非常大,请返回对 109 + 7 取余 后的结果。
子序列 定义为从一个数组里删除一些(或者不删除)元素,但不改变剩下元素的顺序得到的数组。例如,[3,6,2,7] 就是数组 [0,3,1,6,2,2,7] 的一个子序列。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/sum-of-subsequence-widths
思路
因为子序列通过排序后不会影响子序列类别,所以可以先进行nums数组的排序,然后通过数学推导的方式得出最大值为nums[j]的序列宽度Bj
数学推导公式如下图
所以最后的结果为所有Bj的和
通过公式推导发现每次只需要对xj ,yj的值进行更新就能获得Bj的值
且
-
yj+1=yj*2
-
xj+1=xj*2+nums[j]
所以可以通过数学推导方式计算出子序列宽度之和
注意:由于题目要求对10e9+7求模,所以
x、y、ans需要用long类型来存 因为nums[i]*(y-1)在int类型下可能会出现溢出情况。
代码
class Solution {
public int sumSubseqWidths(int[] nums) {
int mod = 1000000007;
Arrays.sort(nums);
long y = 2;
long x = nums[0];
long ans = 0;
for(int i =1;i< nums.length;i++){
ans=(ans+(nums[i]*(y-1)-x+mod))%mod;
y = (y*2)%mod;
x = (x*2+nums[i])%mod;
}
return (int)(ans);
}
}
- 时间复杂度:O(nlogn+n),其中 n 是数组nums的长度,求解所有 Bj 需要 O(n)。
- 空间复杂度:O(logn),排序需要 O(logn) 的栈空间。
Push myself.
求点赞 关注 评论 不定期更新~👍