1588. 所有奇数长度子数组的和

563 阅读2分钟

这是我参与8月更文挑战的第29天,活动详情查看:8月更文挑战

1588. 所有奇数长度子数组的和

给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。

子数组 定义为原数组中的一个连续子序列。

请你返回 arr 中 所有奇数长度子数组的和 。

截屏2021-08-29 上午10.40.06.png

思路分析

子数组和的定义为我们降低了不少难度,再加上可预见的大量的数组求和,我们很容易想到可以通过前缀和的方法解决问题

通过两层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;

但是是否是最优解了呢?

这样的时间复杂度是O(n2)O(n^2)

我们换个角度,不计算一个起点共有几个奇数数组,而是计算携带一个数字的奇数数组出现过几次。

这个数字要怎么计算呢?

利用数组连续

设一个数组长度len,起点a为第i个元素,那么len - i就是a右边的元素,i - 1就是数组左边的元素,如果len为奇数,那么要么是len - i 和 i- 1同时为奇数,要么同时为偶数。

换句话说,我们只需要求出一个数字i,他的左边奇数的数量,左边偶数的数量,右边奇数的数量,右边偶数的数量,我们就可以求出携带这个数字的奇数数组出现过几次。

需要注意的是:记得考虑左边为0,右边为0的情况,因此自己本身也是一个奇数数组。