这是我参与8月更文挑战的第29天,活动详情查看:8月更文挑战
1588. 所有奇数长度子数组的和
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和 。
思路分析
子数组和的定义为我们降低了不少难度,再加上可预见的大量的数组求和,我们很容易想到可以通过前缀和的方法解决问题
通过两层for循环,不断遍历起点和对应的奇数数组长度,来累加出所有奇数长度子数组和。
for(int i = 0; i < arr.size(); i ++)
for(int len = 1; i + len - 1 < arr.size(); len += 2)
res += presum[i + len] - presum[i];
return res;
但是是否是最优解了呢?
这样的时间复杂度是。
我们换个角度,不计算一个起点共有几个奇数数组,而是计算携带一个数字的奇数数组出现过几次。
这个数字要怎么计算呢?
利用数组连续
设一个数组长度len,起点a为第i个元素,那么len - i就是a右边的元素,i - 1就是数组左边的元素,如果len为奇数,那么要么是len - i 和 i- 1同时为奇数,要么同时为偶数。
换句话说,我们只需要求出一个数字i,他的左边奇数的数量,左边偶数的数量,右边奇数的数量,右边偶数的数量,我们就可以求出携带这个数字的奇数数组出现过几次。
需要注意的是:记得考虑左边为0,右边为0的情况,因此自己本身也是一个奇数数组。