给出一个数组,找到所有子数组,然后将其乘以子数组的最后一个元素,然后求和。
例如:[1,2,3] ans = 1 * 1 + 2 * 2 + 3 * 3 +(1 + 2)* 2 +(2 + 3)* 3 +(1 + 2 + 3)* 3 = 53
我尝试了以下逻辑:
init_sum = sum (array)
prev = array[0];
ans = 0
for i = 1 to n:
ans += array[i]* array[i]*(init_sum-prev)
init_sum -= prev
prev = array[i]
end loop
ans += sum(array)
print(ans)
但这不适用于具有重复元素的数组
例如:[1,3,3],我得到的是ans = 88,应该是70。
任何提示将不胜感激。
答案 0 :(得分:8)
数组的每个元素都有一个递归公式。
对于第ith个元素,我们可以注意到该元素对总和的贡献等于在该元素处结束的所有子数组的总和乘以该元素本身的值。 即
对于数组data[a, b, c, d]
,结果将是:
result = a * a
+ ((a + b) + b) * b
+ ((a + b + c) + (b + c) + c) * c
+ ((a + b + c + d) + (b + c + d) + (c + d) + d) * d
将要乘以ith元素的值的因子称为xi
,我们观察到
xi = x(i - 1) + i*data[i]
因此,在上述数组的情况下
x1 = a
x2 = ((a + b) + b) = x1 + 2*b
x3 = ((a + b + c) + (b + c) + c) = x2 + 3*c
x4 = ((a + b + c + d) + (b + c + d) + (c + d) + d) = x3 + 4*d
因此,我们有解决方案
init_sum = 0
ans = 0
for i = 0 to n:
init_sum = init_sum + (i + 1)*array[i]
ans += init_sum*array[i]
end loop
print(ans)
答案 1 :(得分:1)
您追求的算法可以分为以下步骤:
1-生成给定数组的power set。
2-对于每个集合,将数组中的每个元素相加,选择当前集合中的最后一个元素,然后将其与该集合的总和相乘。将此sum
添加到totalsum
让我们在[1 3 3]中看到这一点,我使用下面的算法生成功率集并将其存储在res
步骤1:
void generateSubsets(int i, vector<int>& nums, vector<int>& holder, vector<vector<int>>& res)
{
if(i >= nums.size())
{
res.push_back(holder);
return;
}
holder.push_back(nums[i]);
generateSubsets(i+1,nums,holder,res);
holder.pop_back();
generateSubsets(i+1,nums,holder,res);
}
我将此函数称为:
vector<vector<int>> res;
vector<int> holder;
vector<int> nums = {1,3,3};
generateSubsets(0,nums,holder,res);
res
中生成的子集为:
[1 3 3],[1 3],[1 3],[1],[3 3],[3],[3]
第2步:将集合中的每个元素相加并乘以集合中的最后一个元素,这样就可以了。
[1+3+3]*3 + [1+3]*3 + [1+3]*3 + [1]*1 + [3*3]*3 + [3]*3 + [3]*3
累积totalsum
将为:
totalsum = 21 + 12 + 12 + 1 + 18 + 3 + 3
= 70