Facebook Pixel

3427. Sum of Variable Length Subarrays


Problem Description

You are given an integer array nums of size n. For each index i where 0 <= i < n, define a subarray nums[start ... i] where start = max(0, i - nums[i]). Your task is to compute the total sum of all elements from this subarray defined for each index in the array.

Intuition

To solve the problem, observe that for each index i, you can derive a subarray starting from max(0, i - nums[i]) to i. To efficiently sum all elements in these subarrays, you can use prefix sums. A prefix sum array provides cumulative totals, allowing us to rapidly calculate the sum of any subarray by taking advantage of previously computed results.

In the implementation, you first calculate the prefix sum array s, where each element at index j represents the sum of the nums array elements from the start up to j-1. By storing a zero as an initial element, s[i + 1] - s[start] will give the sum of elements from start to i, where start is max(0, i - nums[i]). This allows us to compute the sum across all defined subarrays in a single pass through the nums array.

Learn more about Prefix Sum patterns.

Solution Approach

The solution employs a prefix sum array to efficiently calculate the total sum of elements in the specified subarrays for each index. Here's how it works:

  1. Prefix Sum Calculation:

    • Use Python's accumulate from the itertools module to compute the prefix sums of the nums array.
    • Initialize the accumulate with 0 to handle the sum from the beginning of the array conveniently.
    • The resulting array s will have s[i] storing the sum of elements from nums[0] to nums[i-1].
  2. Compute Subarray Sums:

    • Use a generator expression within the sum function to iterate over each index i of nums.
    • For each index i, compute the sum of subarray elements using the formula s[i + 1] - s[max(0, i - nums[i])].
    • This formula calculates the sum from the start of the subarray, determined by max(0, i - nums[i]), to the current index i.
  3. Efficiency:

    • The prefix sum allows for efficient computation, reducing the problem to linear time complexity, O(n), while using O(n) additional space for storing prefix sums.

Here's the implementation:

class Solution:
    def subarraySum(self, nums: List[int]) -> int:
        s = list(accumulate(nums, initial=0))
        return sum(s[i + 1] - s[max(0, i - x)] for i, x in enumerate(nums))

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the problem using a small example to illustrate the solution approach.

Example Input:
nums = [3, 2, 1]

Steps:

  1. Compute the Prefix Sums:

    We first compute the prefix sum array s. Initialize s by using accumulate with an initial value of 0:

    • s[0] = 0 (initial value)
    • s[1] = nums[0] = 3
    • s[2] = nums[0] + nums[1] = 3 + 2 = 5
    • s[3] = nums[0] + nums[1] + nums[2] = 3 + 2 + 1 = 6

    So, the prefix sum array s becomes [0, 3, 5, 6].

  2. Calculate the Subarray Sums:

    Now, calculate the sum of subarrays defined by each index i:

    • For i = 0:
      • start = max(0, 0 - nums[0]) = 0
      • Sum of subarray nums[0...0] = s[1] - s[0] = 3 - 0 = 3
    • For i = 1:
      • start = max(0, 1 - nums[1]) = 0
      • Sum of subarray nums[0...1] = s[2] - s[0] = 5 - 0 = 5
    • For i = 2:
      • start = max(0, 2 - nums[2]) = 1
      • Sum of subarray nums[1...2] = s[3] - s[1] = 6 - 3 = 3
  3. Total Sum of All Subarrays:

    Add up the results from step 2:

    • Total sum = 3 (from i = 0) + 5 (from i = 1) + 3 (from i = 2) = 11

Thus, by summarizing the subarrays for each index i, we achieve an efficient solution with a total sum of 11 for the array nums = [3, 2, 1].

Solution Implementation

1from typing import List
2from itertools import accumulate
3
4class Solution:
5    def subarraySum(self, nums: List[int]) -> int:
6        # Compute prefix sums with an initial value of 0 for easier sum calculation
7        prefix_sums = list(accumulate(nums, initial=0))
8      
9        # Calculate the sum of subarrays using prefix sums
10        result = 0
11        for i, num in enumerate(nums):
12            # Find the sum of current subarray
13            # Subtract the prefix sum at the start of the subarray from the prefix sum at the current index + 1
14            # Use max to ensure the starting index does not go below zero
15            result += prefix_sums[i + 1] - prefix_sums[max(0, i - num)]
16          
17        return result
18
1class Solution {
2    public int subarraySum(int[] nums) {
3        int n = nums.length;
4        // Prefix sum array with an extra element for easier calculations
5        int[] prefixSums = new int[n + 1];
6      
7        // Calculate the prefix sums
8        for (int i = 1; i <= n; ++i) {
9            prefixSums[i] = prefixSums[i - 1] + nums[i - 1];
10        }
11      
12        // Initialize answer to store the sum of all subarrays
13        int totalSum = 0;
14      
15        // Iterate over all pairs to find the sum of subarrays 
16        for (int start = 0; start < n; ++start) {
17            for (int end = start; end < n; ++end) {
18                // Calculate subarray sum using prefix sums
19                totalSum += prefixSums[end + 1] - prefixSums[start];
20            }
21        }
22      
23        return totalSum;
24    }
25}
26
1class Solution {
2public:
3    int subarraySum(std::vector<int>& nums) {
4        int n = nums.size(); // Determine the size of the input vector
5        std::vector<int> prefixSum(n + 1, 0); // Initialize a prefix sum vector of size n+1
6
7        // Populate the prefix sum vector
8        for (int i = 1; i <= n; ++i) {
9            prefixSum[i] = prefixSum[i - 1] + nums[i - 1];
10        }
11
12        int totalSum = 0; // Variable to store the answer
13      
14        // Iterate over each element in nums
15        for (int i = 0; i < n; ++i) {
16            // Calculate the sum of subarray ending at the current element
17            totalSum += prefixSum[i + 1] - prefixSum[std::max(0, i - nums[i])];
18        }
19
20        return totalSum; // Return the computed sum
21    }
22};
23
1function subarraySum(nums: number[]): number {
2    // Total length of the input array
3    const n = nums.length;
4  
5    // Initialize an array to store prefix sums, with one extra space for the 0th element
6    const prefixSums: number[] = Array(n + 1).fill(0);
7
8    // Calculate prefix sums
9    for (let i = 0; i < n; ++i) {
10        prefixSums[i + 1] = prefixSums[i] + nums[i];
11    }
12
13    // Initialize the answer to accumulate the sum of the required subarrays
14    let totalSum = 0;
15
16    // Calculate the sum of subarrays based on a sliding window approach
17    for (let i = 0; i < n; ++i) {
18        totalSum += prefixSums[i + 1] - prefixSums[Math.max(0, i - nums[i])];
19    }
20
21    return totalSum;
22}
23

Time and Space Complexity

The time complexity of the code is O(n^2), where n is the length of the list nums. This comes from the nested operations where for each index i, the expression s[i + 1] - s[max(0, i - x)] is computed, resulting in O(n) computations per element of nums.

The space complexity of the code is O(n), as the code constructs a list s using accumulate that stores the prefix sums, which takes space proportional to the length of nums.

Learn more about how to find time and space complexity quickly.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

Which type of traversal does breadth first search do?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More