力扣1588,所有奇数长度子数组的和

该博客介绍了如何通过计算每个元素在所有奇数长度子数组中出现的次数,来求解正整数数组所有奇数长度子数组的和。博主以示例代码解释了如何利用数组元素的位置计算其左右奇数和偶数子数组的数量,并将这些数量与元素值相乘求和,最终得到所有奇数长度子数组的总和。这种方法提高了计算效率,避免了直接遍历的高时间复杂度。
摘要由CSDN通过智能技术生成

题目描述:给你一个正整数数组 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在需要计算的个数。

  最后我们将所有数组中的数字安装上面的方法计算就是最后需要的结果了。

  第一篇博客,写的不是很好,大家多多包涵,如果有错误也可以指正,谢谢大家!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值