2395. Find Subarrays With Equal Sum
Problem Description
You are given a 0-indexed integer array nums
. Your task is to determine whether there exist two subarrays, each of length 2, that have equal sums. These two subarrays must start at different indices in the array.
A subarray is defined as a contiguous non-empty sequence of elements within an array. In this problem, you're specifically looking for subarrays of exactly 2 consecutive elements.
For example:
- If
nums = [1, 2, 3, 4]
, the subarrays of length 2 would be[1, 2]
,[2, 3]
, and[3, 4]
- You need to check if any two of these subarrays have the same sum
- The subarrays
[1, 2]
and[2, 3]
have sums 3 and 5 respectively (different sums) - If any two subarrays had the same sum, you would return
true
The function should return true
if such a pair of subarrays exists, and false
otherwise.
The key insight is that you need to find at least two different pairs of adjacent elements in the array that sum to the same value. Since each subarray of length 2 consists of two adjacent elements, you're essentially looking for duplicate sums among all possible pairs of consecutive elements.
Intuition
The problem asks us to find if there are two subarrays of length 2 with equal sums. Since each subarray of length 2 is just a pair of adjacent elements, we're essentially looking for duplicate sums among all consecutive pairs.
Think about it this way: if we have an array like [4, 2, 4, 1, 3]
, we can calculate the sum of each consecutive pair:
4 + 2 = 6
2 + 4 = 6
4 + 1 = 5
1 + 3 = 4
Notice that the first two pairs both sum to 6, so we have found our answer.
The key realization is that we don't need to store the actual subarrays or their indices - we only care about whether we've seen a particular sum before. This naturally leads us to use a hash table (set) approach:
- As we iterate through the array, we calculate the sum of each consecutive pair
- Before adding a new sum to our set, we check if it already exists
- If it exists, we've found two different subarrays with the same sum
- If it doesn't exist, we add it to the set and continue
This approach works because:
- We process pairs from left to right, so when we encounter a sum we've seen before, we know it must be from a different starting index
- We only need to detect the first duplicate sum to return
true
- Using a set gives us O(1) lookup time to check if we've seen a sum before
The beauty of this solution is its simplicity - we transform the problem from "finding equal subarrays" to "finding duplicate sums", which is a much simpler problem to solve efficiently.
Solution Approach
The solution uses a hash table (set) to track the sums we've encountered while iterating through consecutive pairs of elements.
Here's the step-by-step implementation:
-
Initialize a hash set: Create an empty set called
vis
(visited) to store the sums of consecutive pairs we've seen so far. -
Iterate through consecutive pairs: Use the
pairwise
function to iterate through all consecutive pairs(a, b)
in the array. Thepairwise
function generates tuples of adjacent elements: for array[1, 2, 3, 4]
, it yields(1, 2)
,(2, 3)
,(3, 4)
. -
Calculate and check the sum: For each pair
(a, b)
:- Calculate the sum
x = a + b
- Check if this sum already exists in the
vis
set - If it exists, we've found two different subarrays with equal sums, so return
True
- If it doesn't exist, add this sum to the
vis
set
- Calculate the sum
-
Return false if no duplicates found: If we complete the iteration without finding any duplicate sums, return
False
.
Example walkthrough with nums = [4, 2, 4, 1]
:
- First pair
(4, 2)
: sum = 6,vis
is empty, add 6 tovis = {6}
- Second pair
(2, 4)
: sum = 6, 6 is already invis
, returnTrue
Time Complexity: O(n) where n is the length of the array, as we iterate through the array once.
Space Complexity: O(n) in the worst case where all sums are unique and we store n-1 different sums in the hash set.
The use of the walrus operator :=
in if (x := a + b) in vis:
is a Python optimization that assigns the sum to variable x
while simultaneously checking if it exists in the set, making the code more concise.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [3, 5, 4, 1, 4]
:
Step 1: Initialize
- Create an empty set
vis = {}
to track sums we've seen
Step 2: Process consecutive pairs
Iteration 1: Pair (3, 5)
- Calculate sum:
3 + 5 = 8
- Check if 8 is in
vis
: No - Add 8 to
vis
:vis = {8}
- Continue
Iteration 2: Pair (5, 4)
- Calculate sum:
5 + 4 = 9
- Check if 9 is in
vis
: No - Add 9 to
vis
:vis = {8, 9}
- Continue
Iteration 3: Pair (4, 1)
- Calculate sum:
4 + 1 = 5
- Check if 5 is in
vis
: No - Add 5 to
vis
:vis = {8, 9, 5}
- Continue
Iteration 4: Pair (1, 4)
- Calculate sum:
1 + 4 = 5
- Check if 5 is in
vis
: Yes! (we added it in iteration 3) - We found two subarrays with equal sums:
- Subarray
[4, 1]
starting at index 2 has sum 5 - Subarray
[1, 4]
starting at index 3 has sum 5
- Subarray
- Return
True
The algorithm successfully identifies that two different subarrays of length 2 have the same sum (5), so it returns True
.
Solution Implementation
1class Solution:
2 def findSubarrays(self, nums: List[int]) -> bool:
3 # Set to store sums of consecutive pairs we've seen
4 seen_sums = set()
5
6 # Iterate through all consecutive pairs in the array
7 for i in range(len(nums) - 1):
8 # Calculate sum of current consecutive pair
9 current_sum = nums[i] + nums[i + 1]
10
11 # Check if this sum has been seen before
12 if current_sum in seen_sums:
13 # Found two subarrays with equal sum
14 return True
15
16 # Add current sum to the set of seen sums
17 seen_sums.add(current_sum)
18
19 # No duplicate sums found
20 return False
21
1class Solution {
2 /**
3 * Determines if there exist two subarrays of length 2 with the same sum.
4 *
5 * @param nums the input array of integers
6 * @return true if two subarrays of length 2 have equal sum, false otherwise
7 */
8 public boolean findSubarrays(int[] nums) {
9 // Set to store unique sums of consecutive pairs
10 Set<Integer> visitedSums = new HashSet<>();
11
12 // Iterate through the array starting from index 1
13 for (int i = 1; i < nums.length; i++) {
14 // Calculate sum of current pair (nums[i-1] + nums[i])
15 int currentPairSum = nums[i - 1] + nums[i];
16
17 // Try to add the sum to the set
18 // add() returns false if the element already exists
19 if (!visitedSums.add(currentPairSum)) {
20 // Sum already exists, found duplicate subarray sum
21 return true;
22 }
23 }
24
25 // No duplicate subarray sums found
26 return false;
27 }
28}
29
1class Solution {
2public:
3 bool findSubarrays(vector<int>& nums) {
4 // Set to store sums of consecutive pairs we've seen
5 unordered_set<int> seenSums;
6
7 // Iterate through the array starting from index 1
8 // to check all consecutive pairs
9 for (int i = 1; i < nums.size(); ++i) {
10 // Calculate sum of current pair (previous element + current element)
11 int currentSum = nums[i - 1] + nums[i];
12
13 // Check if this sum has been seen before
14 if (seenSums.count(currentSum)) {
15 // Found two subarrays with equal sum
16 return true;
17 }
18
19 // Add current sum to the set of seen sums
20 seenSums.insert(currentSum);
21 }
22
23 // No duplicate sums found
24 return false;
25 }
26};
27
1/**
2 * Finds if there exist two subarrays of length 2 with equal sum
3 * @param nums - The input array of numbers
4 * @returns true if two subarrays of length 2 have equal sum, false otherwise
5 */
6function findSubarrays(nums: number[]): boolean {
7 // Set to store unique sums of consecutive pairs
8 const seenSums: Set<number> = new Set<number>();
9
10 // Iterate through the array starting from index 1
11 for (let i = 1; i < nums.length; i++) {
12 // Calculate the sum of current element and its predecessor
13 const currentSum: number = nums[i - 1] + nums[i];
14
15 // Check if this sum has been seen before
16 if (seenSums.has(currentSum)) {
17 // Found two subarrays with equal sum
18 return true;
19 }
20
21 // Add the current sum to the set
22 seenSums.add(currentSum);
23 }
24
25 // No duplicate sums found
26 return false;
27}
28
Time and Space Complexity
Time Complexity: O(n)
The algorithm iterates through the array once using pairwise(nums)
, which generates n-1
pairs of consecutive elements where n
is the length of the array. For each pair, it performs:
- Computing the sum
a + b
:O(1)
- Checking membership in the set
x in vis
:O(1)
average case - Adding to the set
vis.add(x)
:O(1)
average case
Since we perform constant-time operations for each of the n-1
pairs, the overall time complexity is O(n)
.
Space Complexity: O(n)
The space is used by:
- The set
vis
which stores the sums of consecutive pairs. In the worst case, alln-1
sums are unique and stored in the set, requiringO(n)
space. - The
pairwise
iterator usesO(1)
additional space as it generates pairs on-the-fly.
Therefore, the total space complexity is O(n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Confusing Overlapping vs Non-overlapping Subarrays
A common misunderstanding is thinking that the two subarrays cannot share elements. In this problem, subarrays CAN overlap - they just need to start at different indices.
Incorrect assumption: "If nums = [1, 2, 3], subarrays [1, 2] and [2, 3] cannot both be considered because they share element 2"
Correct understanding: These subarrays are valid to compare because they start at different indices (0 and 1 respectively). The problem only requires different starting positions, not completely disjoint subarrays.
2. Off-by-One Error in Loop Range
Pitfall Code:
# WRONG - iterates one element too far
for i in range(len(nums)):
current_sum = nums[i] + nums[i + 1] # IndexError when i = len(nums) - 1
Solution: Always use range(len(nums) - 1)
when accessing nums[i]
and nums[i + 1]
to avoid index out of bounds errors.
3. Using a List Instead of a Set
Pitfall Code:
seen_sums = [] # Using list instead of set
for i in range(len(nums) - 1):
current_sum = nums[i] + nums[i + 1]
if current_sum in seen_sums: # O(n) lookup time
return True
seen_sums.append(current_sum)
Issue: Using a list for membership checking makes the algorithm O(n²) instead of O(n), causing time limit exceeded on large inputs.
Solution: Always use a set for O(1) average-case lookup operations.
4. Misunderstanding "Different Indices" Requirement
Some might incorrectly check if the indices are completely non-overlapping:
Pitfall Code:
# WRONG - unnecessarily restrictive
sums_with_indices = {}
for i in range(len(nums) - 1):
current_sum = nums[i] + nums[i + 1]
if current_sum in sums_with_indices:
prev_start, prev_end = sums_with_indices[current_sum]
# Incorrectly checking for no overlap at all
if i > prev_end or i + 1 < prev_start:
return True
sums_with_indices[current_sum] = (i, i + 1)
return False
Solution: The problem only requires different starting indices. Simply checking if a sum has been seen before is sufficient - no need to track or validate index positions.
Which of the following is a good use case for backtracking?
Recommended Readings
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 assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!