Medium
题目描述
给你一个整数数组 arr,请返回所有和为奇数的子数组数目。
由于答案可能会很大,请返回答案对 10^9 + 7 取余的结果。
示例 1:
输入:arr = [1,3,5]
输出:4
解释:所有的子数组为 [[1],[1,3],[1,3,5],[3],[3,5],[5]]
所有子数组的和为 [1,4,9,3,8,5]
奇数和为 [1,9,3,5],所以答案为 4
示例 2:
输入:arr = [2,4,6]
输出:0
解释:所有的子数组为 [[2],[2,4],[2,4,6],[4],[4,6],[6]]
所有子数组的和为 [2,6,12,4,10,6]
所有子数组的和都是偶数,答案为 0
示例 3:
输入:arr = [1,2,3,4,5,6,7]
输出:16
提示:
1 <= arr.length <= 10^51 <= arr[i] <= 100
解题思路
这道题可以使用前缀和的思想来解决。关键观察是:一个子数组的和为奇数,当且仅当该子数组的起始位置和结束位置的前缀和奇偶性不同。
具体思路:
- 遍历数组,维护前缀和
- 用两个变量
even和odd分别记录前缀和为偶数和奇数的位置数量 - 对于当前位置 i,如果前缀和为奇数,那么以位置 i 结尾的奇数和子数组个数等于之前所有前缀和为偶数的位置数量(包括位置 -1,即空前缀)
- 如果前缀和为偶数,那么以位置 i 结尾的奇数和子数组个数等于之前所有前缀和为奇数的位置数量
初始时 even = 1(表示空前缀和为 0,是偶数),odd = 0。
时间复杂度:O(n),只需要遍历一次数组 空间复杂度:O(1),只使用常数个变量
这种方法避免了暴力枚举所有子数组,是最优解。
代码实现
class Solution {
public:
int numOfSubarrays(vector<int>& arr) {
const int MOD = 1e9 + 7;
int even = 1, odd = 0; // 偶数和奇数前缀和的个数
int prefixSum = 0;
int result = 0;
for (int num : arr) {
prefixSum += num;
if (prefixSum % 2 == 0) {
result = (result + odd) % MOD;
even++;
} else {
result = (result + even) % MOD;
odd++;
}
}
return result;
}
};
class Solution:
def numOfSubarrays(self, arr: List[int]) -> int:
MOD = 10**9 + 7
even, odd = 1, 0 # 偶数和奇数前缀和的个数
prefix_sum = 0
result = 0
for num in arr:
prefix_sum += num
if prefix_sum % 2 == 0:
result = (result + odd) % MOD
even += 1
else:
result = (result + even) % MOD
odd += 1
return result
public class Solution {
public int NumOfSubarrays(int[] arr) {
const int MOD = 1000000007;
int even = 1, odd = 0; // 偶数和奇数前缀和的个数
int prefixSum = 0;
int result = 0;
foreach (int num in arr) {
prefixSum += num;
if (prefixSum % 2 == 0) {
result = (result + odd) % MOD;
even++;
} else {
result = (result + even) % MOD;
odd++;
}
}
return result;
}
}
/**
* @param {number[]} arr
* @return {number}
*/
var numOfSubarrays = function(arr) {
const MOD = 1000000007;
let oddCount = 0;
let evenCount = 1;
let result = 0;
let sum = 0;
for (let num of arr) {
sum += num;
if (sum % 2 === 0) {
result = (result + oddCount) % MOD;
evenCount++;
} else {
result = (result + evenCount) % MOD;
oddCount++;
}
}
return result;
};
复杂度分析
| 复杂度 | 大O表示法 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |