元宝DeepSeek LeetCode 891.子序列宽度之和 public int sumSubseqWidths(int[] nums)
题目要求计算数组所有非空子序列的宽度之和,其中宽度定义为子序列的最大值与最小值的差。“nums[i]” 在多少个子序列中作为最大值或最小值出现。“sum(nums[i] * 2^(n-1-i))”,两者相减即得结果。“n-1-i” 个元素每个可选可不选)。那么,所有子序列的最大值之和为。“i” 个元素每个可选可不选),作为最小值的子序列个数为。“sum(nums[i] * 2^i)”,最小值之和为
题目要求计算数组所有非空子序列的宽度之和,其中宽度定义为子序列的最大值与最小值的差。由于子序列数量众多,直接枚举会超时,需要寻找更高效的方法。
关键思路:对数组排序后,每个元素
“nums[i]” 在多少个子序列中作为最大值或最小值出现。具体来说,排序后,
“nums[i]” 作为最大值的子序列个数为
“2^i”(因为比它小的
“i” 个元素每个可选可不选),作为最小值的子序列个数为
“2^(n-1-i)”(因为比它大的
“n-1-i” 个元素每个可选可不选)。那么,所有子序列的最大值之和为
“sum(nums[i] * 2^i)”,最小值之和为
“sum(nums[i] * 2^(n-1-i))”,两者相减即得结果。
算法步骤:
- 对数组排序。
- 预处理
“2^i” 对
“10^9+7” 取模的结果。 - 遍历数组,累加
“nums[i] * (2^i - 2^(n-1-i))”。 - 返回结果,注意处理负数取模。
代码:
class Solution {
public int sumSubseqWidths(int[] nums) {
final int MOD = 1_000_000_007;
Arrays.sort(nums);
int n = nums.length;
long[] pow2 = new long[n];
pow2[0] = 1;
for (int i = 1; i < n; i++) {
pow2[i] = (pow2[i - 1] * 2) % MOD;
}
long ans = 0;
for (int i = 0; i < n; i++) {
ans = (ans + nums[i] * (pow2[i] - pow2[n - 1 - i])) % MOD;
}
return (int) ((ans + MOD) % MOD);
}
}
更多推荐




所有评论(0)