题目描述:给你一个正整数数组 arr
,请你计算所有可能的奇数长度子数组的和。子数组 定义为原数组中的一个连续子序列。
示例:
输入: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
代码部分:
int sumOddLengthSubarrays(vector<int>& arr) {
int n = arr.size();
int sum = 0;
for (int i = 0; i < n; i++)
{
//左边奇数的情况
int leftodd = (i + 1)/ 2 ;
//右边奇数的情况
int rightodd = (n - (i +1) +1) / 2 ;
int allodd = rightodd * leftodd;
//左边偶数的情况
int lefteven = i / 2+1;
//右边偶数的情况
int righteven = (n - i - 1 ) / 2+1;
int allevent = righteven * lefteven;
sum += arr[i] * (allodd + allevent);
}
return sum;
}
做题方法:
首先可以直接根据遍历的方法,利用for循环也可以直接做,但是时间复杂度也比较高,所以就想到了这种利用他的规律去解题,因为每个位置的数他计算的都是有规律的
首先我的想法是计算数组中每个元素需要计算的次数,之后用数组元素乘上它需要计算的个数,那么我们将数组中所有的数字乘上它需要计算的个数得到的这个值,最后将所有数字的这个值相加就是需要计算的奇数子序列之和了
假设数组:Arr= { 1, 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ; n=9 (Arr.size)
用数组中的数字3举例:
数组中3的小标:2 ; i= 2。
下面我们来计算数字3需要计算的次数:
i左边的奇数:i+1 / 2 ; i(数字3)他左边的元素为2个,所以他左边的奇数个数就为(i+1)/2。
i右边的奇数:(n-(i+1)+1) / 2;i(数字3)他右边的元素为n-(i+1)个,所以他左边的奇数个数就为(n-i-1) / 2,为什么是n-(i+1),因为i是从下标0开始计算的,但是n不是,他是数组的长度,根据奇数的计算方法:(n-(i+1)+1) / 2。
i左边的偶数:(i /2)+1; 偶数的计算方法,i(数字3)他左边的元素为2个,所以他左边的偶数个数就为(i /2)+1。
i右边的偶数:(n-(i+1)/2 +1 ;i(数字3)他右边的元素为n-(i+1)个,所以他有边的偶数个数就为(n-i-1) / 2+1,为什么是n-(i+1),因为i是从下标0开始计算的,但是n不是,他是数组的长度。
那么我们来看一下他的计算规律:
根据上面的举例:计算出的i左边的3奇数个数位置,3 右边的奇数个数位置,3左边的偶数个数位置,3右边的个数位置,根据题目:请你计算所有可能的奇数长度子数组的和。子数组 定义为原数组中的一个连续子序列。那么就用数组中的数字3进行举例计算:首先奇数子序列等于 (数字3 左边的奇数个数 乘上 数字3右边的奇数子个数) + (数字3 左边的偶数个数 乘上 数字三右边的偶数子个数)。
那么我们来先看一下 数字3 左边的奇数个数 乘上 数字3右边的奇数子个数 :因为奇数加上奇数+1(数字3)=奇数
数字3 左边的偶数个数 乘上 数字三右边的偶数子个数:偶数+偶数+1(数字3)=奇数
因为我们计算的时候是算的数字3 左边的奇数个数,不包含数字3 ,所以我们在计算的时候要+1,把这个数字3加上,最后得到的这个数就是包含数字3的所有奇数子序列,因为他要算的是所有的奇数子序列,所以数字3乘上包含他的所有奇数子序列的个数,就是数字3在需要计算的个数。
最后我们将所有数组中的数字安装上面的方法计算就是最后需要的结果了。
第一篇博客,写的不是很好,大家多多包涵,如果有错误也可以指正,谢谢大家!