Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1524. Number of Sub-arrays With Odd Sum - Leetcode Solution

Code Implementation

class Solution:
    def numOfSubarrays(self, arr):
        MOD = 10**9 + 7
        odd = even = 0
        result = 0
        for num in arr:
            if num % 2 == 0:
                even += 1
            else:
                # swap odd and even, then increment odd
                odd, even = even, odd
                odd += 1
            result = (result + odd) % MOD
        return result
      
class Solution {
public:
    int numOfSubarrays(vector<int>& arr) {
        int MOD = 1e9 + 7;
        int odd = 0, even = 0, result = 0;
        for (int num : arr) {
            if (num % 2 == 0) {
                even++;
            } else {
                int temp = odd;
                odd = even + 1;
                even = temp;
            }
            result = (result + odd) % MOD;
        }
        return result;
    }
};
      
class Solution {
    public int numOfSubarrays(int[] arr) {
        int MOD = 1000000007;
        int odd = 0, even = 0, result = 0;
        for (int num : arr) {
            if (num % 2 == 0) {
                even++;
            } else {
                int temp = odd;
                odd = even + 1;
                even = temp;
            }
            result = (result + odd) % MOD;
        }
        return result;
    }
}
      
var numOfSubarrays = function(arr) {
    const MOD = 1e9 + 7;
    let odd = 0, even = 0, result = 0;
    for (let num of arr) {
        if (num % 2 === 0) {
            even++;
        } else {
            let temp = odd;
            odd = even + 1;
            even = temp;
        }
        result = (result + odd) % MOD;
    }
    return result;
};
      

Problem Description

Given an array of integers arr, count the number of contiguous subarrays whose sum is odd. The result should be returned modulo 10^9 + 7 due to potentially large output. Each subarray must have at least one element, and you should consider all possible contiguous subarrays.

Thought Process

At first glance, the brute-force approach would be to check every possible subarray, compute its sum, and count how many sums are odd. However, this would be too slow for large arrays since the number of subarrays grows quadratically. To optimize, we look for patterns. Notice that the parity (odd or even) of a sum depends on the parity of the numbers included. If we can efficiently track the number of subarrays ending at each index with an odd sum, we can sum these up for the answer. This leads to considering prefix sums and how their parity changes as we iterate through the array.

Solution Approach

To solve the problem efficiently, we use the following strategy:
  • We maintain two counters: odd and even, where odd is the number of prefix sums with odd sum up to the current index, and even is the number of prefix sums with even sum up to the current index.
  • Initially, the count of even prefix sums is 1 (the empty prefix), and the count of odd prefix sums is 0.
  • As we iterate through each element:
    • If the current number is even, it does not change the parity of the prefix sum. So, the number of odd and even prefix sums remains the same, except we increment the number of even prefixes by 1 (for the new prefix ending at the current element).
    • If the current number is odd, it flips the parity of the prefix sum. So, the number of new odd prefixes becomes the previous even count (because even + odd = odd), and the number of new even prefixes becomes the previous odd count (because odd + odd = even). We also increment the count for the current element itself.
  • At each step, the number of subarrays ending at the current index with an odd sum is equal to the current odd count.
  • Sum up odd for each index to get the final answer.
This approach ensures we only make a single pass through the array, and all operations are constant time per element.

Example Walkthrough

Let's walk through the example arr = [1, 3, 5]:
  • Start: odd = 0, even = 0, result = 0
  • First element (1):
    • 1 is odd, so swap odd/even: odd = 0, even = 0; then odd += 1 → odd = 1
    • result += odd → result = 1
  • Second element (3):
    • 3 is odd, so swap odd/even: odd = 0, even = 1; then odd += 1 → odd = 2
    • result += odd → result = 3
  • Third element (5):
    • 5 is odd, so swap odd/even: odd = 1, even = 2; then odd += 1 → odd = 3
    • result += odd → result = 6
The answer is 6, corresponding to all possible subarrays: [1], [3], [5], [1,3], [3,5], [1,3,5], among which [1], [3], [5], [1,3,5] have odd sums.

Time and Space Complexity

  • Brute-force approach: For every subarray, calculate the sum and check if it is odd. There are O(n2) subarrays, and each sum takes O(1) time if we use prefix sums, so total time is O(n2).
  • Optimized approach (as above): We only need one pass through the array, updating counters in O(1) time per element. So, the total time complexity is O(n).
  • Space complexity for both approaches is O(1) (not counting the input array), since we use only a few integer variables for counters.

Summary

By recognizing the relationship between prefix sums and the parity of subarrays, we avoid the brute-force enumeration of all subarrays. Using two simple counters for odd and even prefix sums, we efficiently count the number of subarrays with odd sums in a single pass, making this solution both elegant and highly performant.