LeetCode Everyday - 和为奇数的子数组数目

111 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

和为奇数的子数组数目

给你一个整数数组 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

示例4:

输入: arr = [100,100,99,99]
输出: 4

示例5:

输入: arr = [7]
输出: 1

提示:

  • 1 <= arr.length <= 10^5
  • 1 <= arr[i] <= 100

解题思路:

一开始用递归写,但是数组太长会报函数调用太多次的错,所以改成 for 循环就好了

  1. 首先明确:奇+奇=偶,奇+偶=奇,偶+偶=偶
  2. 倒着遍历数组
  3. 如果当前数是奇数,以 arr[i] 开头的和为奇数的子数组数量 = 以 arr[i + 1] 开头的和为偶数的子数组数量 + 1(自身)
  4. 如果当前数是偶数,以 arr[i] 开头的和为奇数的子数组数量 = 以 arr[i + 1] 开头的和为奇数的子数组数量
  5. 用两个临时变量存储每个节点的奇偶子数组,方便计算

我的答案:

/**
 * @param {number[]} arr
 * @return {number}
 */
var numOfSubarrays = function(arr) {
    if (!arr.length) return 0
    let res = 0
    let nextOdd = 0 // 临时存放以下一个数开头的和为奇数的子数组数量
    let nextEven = 0 // 临时存放以下一个数开头的和为奇数的偶数组数量
    // 奇+奇=偶,奇+偶=奇,偶+偶=偶
    // 倒着遍历数组,nextOdd 和 nextEven 会不断更新
    for (let i = arr.length - 1; i >= 0; i--) {
        if (i === arr.length - 1) {
            // 最后一个数,子数组只有它自身
            if (arr[i] & 1) {
                res++
                nextOdd = 1
                nextEven = 0
            } else {
                nextOdd = 0
                nextEven = 1
            }
        } else if (arr[i] & 1) {
            /**
             * 当前是奇数
             * 以 arr[i] 开头的和为奇数的子数组数量 = 以 arr[i + 1] 开头的和为偶数的子数组数量 + 1(自身)
             * 以 arr[i] 开头的和为偶数的子数组数量 = 以 arr[i + 1] 开头的和为奇数的子数组数量
             */
            res += nextEven + 1;
            [nextOdd, nextEven] = [nextEven + 1, nextOdd]
        } else {
            /**
             * 当前是偶数
             * 以 arr[i] 开头的和为奇数的子数组数量 = 以 arr[i + 1] 开头的和为奇数的子数组数量
             * 以 arr[i] 开头的和为偶数的子数组数量 = 以 arr[i + 1] 开头的和为偶数的子数组数量 + 1(自身)
             */
            res += nextOdd
            nextEven++
        }
    }
    return res % (Math.pow(10, 9) + 7)
};

最后

如果有更好的解法或者思路, 欢迎在评论区和我交流~ ღ( ´・ᴗ・` )