所有奇数长度子数组的和
题目:给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和 。
示例 1:
输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
示例 2:
输入:arr = [1,2]
输出:3
解释:总共只有 2 个长度为奇数的子数组,[1] 和 [2]。它们的和为 3 。
示例 3:
输入:arr = [10,11,12]
输出:66
提示:
1 <= arr.length <= 100
1 <= arr[i] <= 1000
解题思路
解法一
我们只需要枚举所有的奇数长度的子数组即可。在下面的代码中,i 用来枚举每个连续子数组的起点,gap为连续子数组的长度。accumulate用来计算起点是 i,长度为 gap 的子数组的和。时间复杂度是 O(n^3) 的。
代码展示
代码如下:
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int sum=0,n=arr.size();
for(int i=0;i<n;i++)
{
for(int gap=1;i+gap-1<n;gap+=2)
{
sum+=accumulate(arr.begin()+i,arr.begin()+i+gap,0);
}
}
return sum;
}
};
解法二
就是遍历一遍所有的元素,然后查看这个元素会在多少个长度为奇数的数组中出现过。
比如题目给出的第一个测试用例 [1, 4, 2, 5, 3] 中;
1 在 3 个长度为奇数的数组中出现过:[1], [1, 4, 2], [1, 4, 2, 5, 3];所以最终的和,要加上 1 * 3;
4 在 4 个长度为奇数的数组中出现过:[4], [4, 2, 5], [1, 4, 2], [1, 4, 2, 5, 3];所以最终和,要加上 4 * 4;
2 在 5 个长度为奇数的数组中出现过:[2], [2, 5, 3], [4, 2, 5], [1, 4, 2], [1, 4, 2, 5, 3];所以最终和,要加上 5 * 2;
…
下面的关键就是,如何计算一个数字在多少个奇数长度的数组中出现过?
对于一个数字,它所在的数组,可以在它前面再选择 0, 1, 2, … 个数字,一共有 left = i + 1 个选择;
可以在它后面再选择 0, 1, 2, … 个数字,一共有 right = n - i 个选择。
如果在前面选择了偶数个数字,那么在后面,也必须选择偶数个数字,这样加上它自身,才构成奇数长度的数组;
如果在前面选择了奇数个数字,那么在后面,也必须选择奇数个数字,这样加上它自身,才构成奇数长度的数组;
数字前面共有 left 个选择,其中偶数个数字的选择方案有 left_even = (left + 1) / 2 个,奇数个数字的选择方案有 left_odd = left / 2 个;
数字后面共有 right 个选择,其中偶数个数字的选择方案有 right_even = (right + 1) / 2 个,奇数个数字的选择方案有 right_odd = right / 2 个;
所以,每个数字一共在 left_even * right_even + left_odd * right_odd 个奇数长度的数组中出现过。
链接:https://leetcode-cn.com/problems/sum-of-all-odd-length-subarrays/solution/cong-on3-dao-on-de-jie-fa-by-liuyubobobo/
代码展示
代码如下:
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int res=0;
for(int i=0;i<arr.size();i++)
{
int left=i+1,right=arr.size()-i,
left_even=(left+1)/2,left_odd=left/2,
right_even=(right+1)/2,right_odd=right/2;
res+=(left_even*right_even+left_odd*right_odd)*arr[i];
}
return res;
}
};