题目
给你一个下标从 0 开始的整数数组 nums
,它表示英雄的能力值。如果我们选出一部分英雄,这组英雄的 力量 定义为:
i0
,i1
,…ik
表示这组英雄在数组中的下标。那么这组英雄的力量为max(nums[i0],nums[i1] ... nums[ik])^2 * min(nums[i0],nums[i1] ... nums[ik])
。
请你返回所有可能的 非空 英雄组的 力量 之和。由于答案可能非常大,请你将结果对 10^9 + 7
取余。
示例 1:
输入:nums = [2,1,4]
输出:141
解释:
第 1 组:[2] 的力量为 22 * 2 = 8 。
第 2 组:[1] 的力量为 12 * 1 = 1 。
第 3 组:[4] 的力量为 42 * 4 = 64 。
第 4 组:[2,1] 的力量为 22 * 1 = 4 。
第 5 组:[2,4] 的力量为 42 * 2 = 32 。
第 6 组:[1,4] 的力量为 42 * 1 = 16 。
第 7 组:[2,1,4] 的力量为 42 * 1 = 16 。
所有英雄组的力量之和为 8 + 1 + 64 + 4 + 32 + 16 + 16 = 141 。
示例 2:
输入:nums = [1,1,1]
输出:7
解释:总共有 7 个英雄组,每一组的力量都是 1 。所以所有英雄组的力量之和为 7 。
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9
解题
方法一:暴力
思路
对数组进行排序,因为要用子序列的最小值与最大值。这样就转化为找两个端的问题和该两端的情况下的次数。
时间复杂度太高,超时。
代码
class Solution:
def sumOfPower(self, nums: List[int]) -> int:
n = len(nums)
powersum = 0
MOD = 10**9 + 7
nums.sort()
for step in range(n):
i = 0
j = i + step
while j < n:
if step > 1:
weight = 2**(step-1)
else:
weight = 1
powersum += ((nums[j]**2 * nums[i])*weight)
i += 1
j += 1
return powersum % MOD
方法一:动态规划 + 前缀和
代码
未空间优化版
class Solution:
def sumOfPower(self, nums: List[int]) -> int:
nums.sort()
dp = [0 for i in range(len(nums))]
pre_sum = [0 for i in range(len(nums) + 1)]
res, mod = 0, 10 ** 9 + 7
for i in range(len(nums)):
dp[i] = (nums[i] + pre_sum[i]) % mod
pre_sum[i + 1] = (pre_sum[i] + dp[i]) % mod
res = (res + nums[i] * nums[i] * dp[i]) % mod
return res
「滚动数组」空间优化版
class Solution:
def sumOfPower(self, nums: List[int]) -> int:
nums.sort()
dp, pre_sum = 0, 0
res, mod = 0, 10 ** 9 + 7
for i in range(len(nums)):
dp = (nums[i] + pre_sum) % mod
pre_sum = (pre_sum + dp) % mod
res = (res + nums[i] * nums[i] * dp) % mod
return res
复杂度分析
- 时间复杂度:O(nlogn),其中 n 为数组 nums 的长度。排序需要 O(nlogn) 的时间,动态规划需要 O(n)O(n) 的时间。
- 空间复杂度:O(logn),其中 n 为数组 nums 的长度。排序需要 O(logn) 的递归调用栈空间,动态规划通过「滚动数组」优化后仅使用常量空间。