以下为他人题解思路,及本人代码
题目
题意
给你一个下标从 0 0 0 开始的整数数组 n u m s nums nums ,它表示英雄的能力值。如果我们选出一部分英雄,这组英雄的力量定义为:
i 0 , i 1 , . . . i k i_0 ,i_1 ,... i_k i0,i1,...ik 表示这组英雄在数组中的下标。那么这组英雄的力量为 m a x ( n u m s [ i 0 ] , n u m s [ i 1 ] . . . n u m s [ i k ] ) 2 ∗ m i n ( n u m s [ i 0 ] , n u m s [ i 1 ] . . . n u m s [ i k ] ) max(nums[i_0],nums[i_1] ... nums[i_k])2 * min(nums[i_0],nums[i_1] ... nums[i_k]) max(nums[i0],nums[i1]...nums[ik])2∗min(nums[i0],nums[i1]...nums[ik]) 。
请你返回所有可能的非空英雄组的力量之和。由于答案可能非常大,请你将结果对 1 0 9 + 7 10^9 + 7 109+7 取余。
示例 1
输入: n u m s = [ 2 , 1 , 4 ] nums = [2,1,4] nums=[2,1,4]
输出: 141 141 141
解释:
第 1 1 1 组: [ 2 ] [2] [2] 的力量为 2 2 ∗ 2 = 8 2^2 * 2 = 8 22∗2=8 。
第 2 2 2 组: [ 1 ] [1] [1] 的力量为 1 2 ∗ 1 = 1 1^2 * 1 = 1 12∗1=1 。
第 3 3 3 组: [ 4 ] [4] [4] 的力量为 4 2 ∗ 4 = 64 4^2 * 4 = 64 42∗4=64 。
第 4 4 4 组: [ 2 , 1 ] [2,1] [2,1] 的力量为 2 2 ∗ 1 = 4 2^2 * 1 = 4 22∗1=4 。
第 5 5 5 组: [ 2 , 4 ] [2,4] [2,4] 的力量为 4 2 ∗ 2 = 32 4^2 * 2 = 32 42∗2=32 。
第 6 6 6 组: [ 1 , 4 ] [1,4] [1,4] 的力量为 4 2 ∗ 1 = 16 4^2 * 1 = 16 42∗1=16 。
第 7 组: [ 2 , 1 , 4 ] [2,1,4] [2,1,4] 的力量为 4 2 ∗ 1 = 16 4^2 * 1 = 16 42∗1=16 。
所有英雄组的力量之和为 8 + 1 + 64 + 4 + 32 + 16 + 16 = 141 8 + 1 + 64 + 4 + 32 + 16 + 16 = 141 8+1+64+4+32+16+16=141 。
示例 2
输入: n u m s = [ 1 , 1 , 1 ] nums = [1,1,1] nums=[1,1,1]
输出: 7 7 7
解释:总共有 7 7 7 个英雄组,每一组的力量都是 1 1 1 。所以所有英雄组的力量之和为 7 7 7 。
提示
- 1 < = n u m s . l e n g t h < = 1 0 5 1 <= nums.length <= 10^5 1<=nums.length<=105
- 1 < = n u m s [ i ] < = 1 0 9 1 <= nums[i] <= 10^9 1<=nums[i]<=109
他人思路
贡献法
算法总结
由于元素的顺序不影响答案,先排序。
设有 a , b , c , d , e a,b,c,d,e a,b,c,d,e 五个数,顺序从小到大。
如果把 d d d 当成最大值:
- 如果只选 d d d 单独一个数,那么力量为 d 3 d^3 d3。
- 选 a a a 为最小值,由于中间的 b b b 和 c c c 可选可不选,一共有 2 2 2^2 22 种方案,所以力量总和为 d 2 ∗ a ∗ 2 2 d^2 * a * 2^2 d2∗a∗22。
- 选 b b b 为最小值,由于中间的 c c c 可选可不选,一共有 2 1 2^1 21 种方案,所以力量总和为 d 2 ∗ b ∗ 2 1 d^2 * b * 2^1 d2∗b∗21。
- 选 c c c 为最小值,只有 2 0 = 1 2^0 = 1 20=1 种方案,所以力量总和为 d 2 ⋅ c ⋅ 2 0 d^2⋅c⋅2^0 d2⋅c⋅20。
因此,当 d d d 为最大值时, d d d 及其左侧元素对答案的贡献为
d 3 + d 2 ∗ ( a ∗ 2 2 + b ∗ 2 1 + c ∗ 2 0 ) d^3 + d^2 * (a * 2^2 + b * 2^1 + c * 2^0) d3+d2∗(a∗22+b∗21+c∗20)
令 s = a ∗ 2 2 + b ∗ 2 1 + c ∗ 2 0 s = a * 2^2 + b * 2^1 + c * 2^0 s=a∗22+b∗21+c∗20,上式为
d 3 + d 2 ∗ s = d 2 ∗ ( d + s ) d^3 + d^2 * s = d^2 * (d + s) d3+d2∗s=d2∗(d+s)
继续,把 e e e 当成最大值,观察 s s s 如何变化,也就是 a , b , c , d a,b,c,d a,b,c,d 作为最小值的贡献:
a ∗ 2 3 + b ∗ 2 3 + c ∗ 2 1 + d ∗ 2 0 = 2 ∗ ( a ∗ 2 2 + b ∗ 2 1 + c ∗ 2 0 ) + d ∗ 2 0 = 2 ∗ s + d a * 2^3 + b * 2^3 + c * 2^1 + d * 2^0 \\= 2 * (a * 2^2 + b * 2^1 + c * 2^0) + d * 2^0 \\= 2 * s + d a∗23+b∗23+c∗21+d∗20=2∗(a∗22+b∗21+c∗20)+d∗20=2∗s+d
这意味着,我们不需要枚举最小值,只需要枚举最大值,就可以把 s s s 递推计算出来。
复杂度
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn),其中 n n n 为 n u m s nums nums 的长度。瓶颈在排序上。
- 空间复杂度: O ( 1 ) O(1) O(1)。忽略排序的栈空间,仅用到若干额外变量。
本人代码
Java
class Solution {
public int sumOfPower(int[] nums) {
Arrays.sort(nums);
long mod = (long) 1e9 + 7;
long ans = 0, s = 0;
for (long i : nums) {
ans = (ans + i * i % mod * (i + s)) % mod;
s = (2 * s + i) % mod;
}
return (int) ans;
}
}
提交结果:通过
- 执行用时: 14 m s 14ms 14ms
- 内存消耗: 51.72 M B 51.72MB 51.72MB