2395. Find Subarrays With Equal Sum
Problem Description
The problem is asking us to check if an integer array named nums
, which is 0-indexed, contains at least two subarrays of length 2 with the same sum. Importantly, these two subarrays must start at different indices within the nums
array. We define a subarray as a continuous part of the original array that contains one or more consecutive elements.
For example, given nums = [4,2,4,5,6]
, we have subarrays with length 2 such as [4,2]
, [2,4]
, [4,5]
, and [5,6]
. The question is whether any two of these pairs have an equal sum.
We are to return true
if such subarrays exist or false
otherwise.
Intuition
The intuition behind the solution is to use a set to keep track of sums of all possible subarrays of length 2. Since we're looking for two different subarrays that have the same sum, we can iterate through the nums
array constructing subarrays of length 2 on the fly, sum them up, and then check if their sum has already been encountered before (i.e., it's present in the set).
The steps to arrive at the solution are straightforward:
- Initialize an empty set to store the unique sums of subarrays of length 2.
- Iterate through the
nums
array while considering every adjacent pair of elements as a potential subarray of length 2. - For each pair, calculate the sum and check if this sum has been seen before (i.e., it is in the set).
- If the sum is already in the set, this means we have found another subarray with the same sum, hence we can return
true
. - If it's not, we add the sum to the set and continue with the next pair.
- If the sum is already in the set, this means we have found another subarray with the same sum, hence we can return
- If we finish iterating over the array without finding such a pair, return
false
.
By utilizing the set for the lookup operation, which is O(1) on average, we can ensure that our solution is efficient, with an overall time complexity of O(n) where n is the number of elements in nums
.
Solution Approach
The implementation of the solution approach involves a loop and a set
. The set
data structure is chosen because it provides O(1) lookup time for checking if an element exists, making the overall solution more efficient. This efficiency is central to the algorithm we use to solve the problem.
Here's how the algorithm works step by step:
-
Initialize an empty
set
namedvis
which will store the sums of subarrays of length 2. -
Iterate over the array
nums
using a for loop. Here, we are using Python'spairwise
utility (which, assuming it's similar to or a placeholder foritertools.pairwise
, generates consecutive pairs of elements). For each pair(a, b)
innums
, we perform the following operations inside the loop:- Calculate the sum of the current pair with
x := a + b
. This is an example of Python's walrus operator (:=
), which assigns the value ofa + b
tox
and then allowsx
to be used immediately within the condition. - Check if
x
is already invis
. If it is, that means we have found a previous pair with the same sum, and we can immediately returntrue
. - If
x
is not found invis
, addx
tovis
to keep track of this sum and then continue to the next pair.
- Calculate the sum of the current pair with
-
If the loop completes without returning
true
, no two subarrays with the same sum have been found. Therefore, we returnfalse
.
The pattern used here is known as the 'Sliding Window' pattern, which is commonly used for problems dealing with contiguous subarrays or subsequences of a given size. The sliding window in this solution is of fixed size 2, which slides over the array to consider all subarrays of length 2.
Code
Here is the provided code for the solution:
class Solution:
def findSubarrays(self, nums: List[int]) -> bool:
vis = set()
for a, b in pairwise(nums):
if (x := a + b) in vis:
return True
vis.add(x)
return False
The code succinctly executes the algorithm described and solves the problem effectively with an O(n) time complexity.
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 a small example to illustrate the solution approach using the array nums = [1, 2, 3, 4, 5]
.
-
Initialize an empty set
vis
to store the sums of subarrays of length 2. -
Start iterating over the array to consider all pairs of consecutive numbers:
- First pair:
[1, 2]
- Calculate the sum:
x = 1 + 2
which is3
. - Check if
3
is invis
. It is not, so add3
tovis
. - Now,
vis = {3}
.
- Calculate the sum:
- Second pair:
[2, 3]
- Calculate the sum:
x = 2 + 3
which is5
. - Check if
5
is invis
. It is not, so add5
tovis
. - Now,
vis = {3, 5}
.
- Calculate the sum:
- Third pair:
[3, 4]
- Calculate the sum:
x = 3 + 4
which is7
. - Check if
7
is invis
. It is not, so add7
tovis
. - Now,
vis = {3, 5, 7}
.
- Calculate the sum:
- Fourth and last pair:
[4, 5]
- Calculate the sum:
x = 4 + 5
which is9
. - Check if
9
is invis
. It is not, so add9
tovis
. - Now,
vis = {3, 5, 7, 9}
.
- Calculate the sum:
- First pair:
-
We have finished iterating over the array and have not found any sums that occur more than once in
vis
. Therefore, we returnfalse
, meaning no two subarrays of length 2 with the same sum exist in the arraynums = [1, 2, 3, 4, 5]
.
This small example illustrates how the algorithm effectively checks each subarray of length 2 for a sum that might have appeared before, and efficiently keeps track of the sums using a set.
Solution Implementation
1from itertools import pairwise # Python 3 does not have 'pairwise' in itertools by default. Make sure it's available, or define an equivalent function.
2
3class Solution:
4 def findSubarrays(self, nums):
5 # Initialize a set to store the sum of pairs
6 seen_sums = set()
7
8 # Iterate over pairwise combinations using zip to get adjacent elements.
9 for a, b in zip(nums, nums[1:]):
10 current_sum = a + b
11 # Check if the sum of the current pair has been seen before
12 if current_sum in seen_sums:
13 # If we have seen this sum, a subarray with equal sum exists
14 return True
15 # Add the sum to the set of seen sums
16 seen_sums.add(current_sum)
17
18 # If no two subarrays have the same sum, return False
19 return False
20
1class Solution {
2 public boolean findSubarrays(int[] nums) {
3 // Create a HashSet to store the sums of consecutive elements
4 Set<Integer> seenSums = new HashSet<>();
5
6 // Iterate through the array, starting from the second element
7 for (int i = 1; i < nums.length; ++i) {
8 // Calculate the sum of the current and previous elements
9 int sum = nums[i - 1] + nums[i];
10
11 // Attempt to add the sum to the set
12 boolean isAdded = seenSums.add(sum);
13
14 // If the sum could not be added because it's already present
15 // in the set, then we found a repeated sum and return true
16 if (!isAdded) {
17 return true;
18 }
19 }
20
21 // If the loop completes without returning, no repeating sum was found
22 // so we return false
23 return false;
24 }
25}
26
1#include <vector>
2#include <unordered_set>
3using namespace std; // Directives for convenience, commonly placed at the top
4
5class Solution {
6public:
7 // The function check if there are any subarrays with length 2 that sum to the same value.
8 bool findSubarrays(vector<int>& nums) {
9 unordered_set<int> seenSums; // This set will store the sums of adjacent elements
10
11 // Iterate through the array, stopping one element before the last to avoid out-of-bounds access.
12 for (int i = 1; i < nums.size(); ++i) {
13 int currentSum = nums[i - 1] + nums[i]; // Calculate sum of current and previous element
14
15 // Check if the current sum has already been seen.
16 if (seenSums.count(currentSum)) {
17 return true; // If so, we found two subarrays with the same sum.
18 }
19
20 // If it hasn't been seen, add the current sum to the set of seen sums.
21 seenSums.insert(currentSum);
22 }
23
24 // If we've iterate through all elements without finding duplicate sums, return false.
25 return false;
26 }
27};
28
1function findSubarrays(nums: number[]): boolean {
2 // Initialize a set to keep track of the sums of adjacent pairs previously seen
3 const seenSums: Set<number> = new Set<number>();
4
5 // Loop through each number in the array except the last one
6 for (let i = 1; i < nums.length; ++i) {
7 // Calculate the sum of the current number and the one before it
8 const currentSum = nums[i - 1] + nums[i];
9
10 // Check if the sum has been seen before in the set
11 if (seenSums.has(currentSum)) {
12 // If yes, we have found a duplicate sum of subarrays
13 return true;
14 }
15
16 // Add the current sum to the set
17 seenSums.add(currentSum);
18 }
19
20 // If no duplicate sums of subarrays have been found, return false
21 return false;
22}
23
Time and Space Complexity
The provided Python function findSubarrays
iterates through the nums
list to find if any pair of consecutive elements has a sum that has been seen before. The function utilizes the pairwise
utility to iterate over the list.
Time Complexity:
- The
pairwise
utility returns an iterator that generates pairs of consecutive elements. The loop thus runs exactlyn - 1
times, wheren
is the length ofnums
. - Checking if a sum is in
vis
set has an average time complexity of O(1) due to the nature of set operations in Python. - Adding an element to a set also has an average time complexity of O(1).
Hence, the time complexity of the function can be considered as O(n) because it involves just one pass through the nums
list, with constant-time operations within the loop.
Space Complexity:
- The
vis
set stores sums of consecutive elements. In the worst case, all pairs will have different sums, resulting inn - 1
entries in the set. - This worst-case space complexity of storing the sums is O(n) where
n
is the number of elements in the list.
In conclusion, the function findSubarrays
has a time complexity of O(n)
and a space complexity of O(n)
.
Learn more about how to find time and space complexity quickly using problem constraints.
What does the following code do?
1def f(arr1, arr2):
2 i, j = 0, 0
3 new_arr = []
4 while i < len(arr1) and j < len(arr2):
5 if arr1[i] < arr2[j]:
6 new_arr.append(arr1[i])
7 i += 1
8 else:
9 new_arr.append(arr2[j])
10 j += 1
11 new_arr.extend(arr1[i:])
12 new_arr.extend(arr2[j:])
13 return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2 int i = 0, j = 0;
3 List<Integer> newArr = new ArrayList<>();
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.add(arr1[i]);
8 i++;
9 } else {
10 newArr.add(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.add(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.add(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
1function f(arr1, arr2) {
2 let i = 0, j = 0;
3 let newArr = [];
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.push(arr1[i]);
8 i++;
9 } else {
10 newArr.push(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.push(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.push(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
Recommended Readings
LeetCode 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 we
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
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!