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:
-
Prefix Sum Calculation:
- Use Python's
accumulate
from theitertools
module to compute the prefix sums of thenums
array. - Initialize the accumulate with 0 to handle the sum from the beginning of the array conveniently.
- The resulting array
s
will haves[i]
storing the sum of elements fromnums[0]
tonums[i-1]
.
- Use Python's
-
Compute Subarray Sums:
- Use a generator expression within the
sum
function to iterate over each indexi
ofnums
. - For each index
i
, compute the sum of subarray elements using the formulas[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 indexi
.
- Use a generator expression within the
-
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 EvaluatorExample Walkthrough
Let's walk through the problem using a small example to illustrate the solution approach.
Example Input:
nums = [3, 2, 1]
Steps:
-
Compute the Prefix Sums:
We first compute the prefix sum array
s
. Initializes
by usingaccumulate
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]
. -
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
- For
-
Total Sum of All Subarrays:
Add up the results from step 2:
- Total sum = 3 (from
i = 0
) + 5 (fromi = 1
) + 3 (fromi = 2
) = 11
- Total sum = 3 (from
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.
Which type of traversal does breadth first search do?
Recommended Readings
Prefix Sum The prefix sum is an incredibly powerful and straightforward technique Its primary goal is to allow for constant time range sum queries on an array What is Prefix Sum The prefix sum of an array at index i is the sum of all numbers from index 0 to i By
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!