4Sum II
Problem
Given four integer arrays nums1, nums2, nums3, and nums4 all of length n, return the number of tuples (i, j, k, l) such that nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0.
- n == nums1.length == nums2.length == nums3.length == nums4.length
- 1 ≤ n ≤ 200
- −2²⁸ ≤ nums1[i], nums2[i], nums3[i], nums4[i] ≤ 2²⁸
Example
nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]2The two tuples are: - (0, 0, 0, 1): 1 + (-2) + (-1) + 2 = 0 - (1, 1, 0, 0): 2 + (-1) + (-1) + 0 = 0 A brute-force approach would check all quadruples, which is O(n^4). Instead, the algorithm precomputes sums of pairs from nums1 and nums2, storing their frequencies in a hash map. Then it iterates over pairs from nums3 and nums4, checking if the negated sum exists in the map. This reduces the problem to two nested loops and a hash map lookup, achieving O(n^2) time.
Approach
Straightforward Solution
A brute-force approach enumerates all quadruples (i, j, k, l) and checks if their sum is zero, resulting in O(n^4) time complexity, which is infeasible for n up to 200.
Core Observation
The problem requires counting quadruples where the sum of four elements equals zero. This can be reframed as finding pairs of sums from two arrays that complement pairs of sums from the other two arrays to zero.
Path to Optimal
By splitting the problem into two halves, the sums of pairs from nums1 and nums2 can be precomputed and stored in a hash map with their frequencies. Then, for each pair sum from nums3 and nums4, the algorithm checks if the negated sum exists in the map. This reduces the complexity to O(n^2) for both halves, resulting in an overall O(n^2) time complexity.
Optimal Approach
Compute all possible sums of pairs from nums1 and nums2, storing the count of each sum in a hash map. Then iterate over all sums of pairs from nums3 and nums4, and for each sum, check if its negation exists in the hash map. Accumulate the counts accordingly. This approach leverages the hash map for constant-time lookups, efficiently counting all quadruples summing to zero.
Time
O(n^2)
The algorithm computes all pair sums from nums1 and nums2 in O(n^2), and similarly iterates over all pair sums from nums3 and nums4 in O(n^2). Each hash map lookup is O(1) on average, resulting in O(n^2) total time.
Space
O(n^2)
The hash map stores counts of all possible sums of pairs from nums1 and nums2, which can be up to O(n^2) in the worst case. This auxiliary space is necessary to achieve the time complexity improvement.
Pattern Spotlight
Hash Maps (Complement Counting)
When counting tuples across multiple arrays that sum to a target, precompute sums of pairs from half the arrays and store frequencies in a hash map, then check complements from the other half to reduce complexity from exponential to quadratic.
Solution
| 1 | class Solution: |
| 2 | def fourSumCount(self, nums1, nums2, nums3, nums4): |
| 3 | |
| 4 | pair_count = {} |
| 5 | result = 0 |
| 6 | |
| 7 | for a in nums1: |
| 8 | for b in nums2: |
| 9 | pair_sum = a + b |
| 10 | pair_count[pair_sum] = pair_count.get(pair_sum, 0) + 1 |
| 11 | |
| 12 | for c in nums3: |
| 13 | for d in nums4: |
| 14 | target = -(c + d) |
| 15 | if target in pair_count: |
| 16 | result += pair_count[target] |
| 17 | |
| 18 | return result |
Step-by-Step Solution
Build frequency map of sums from nums1 and nums2 pairs
| 4 | pair_count = {} |
| 5 | result = 0 |
| 7 | for a in nums1: |
| 8 | for b in nums2: |
| 9 | pair_sum = a + b |
| 10 | pair_count[pair_sum] = pair_count.get(pair_sum, 0) + 1 |
Objective
To count how many times each possible sum of elements from nums1 and nums2 occurs.
Key Insight
Precomputing sums of pairs from the first two arrays and storing their frequencies in a hash map enables constant-time lookups later. This reduces the problem's complexity by collapsing two nested loops into a single data structure that summarizes all pair sums.
Interview Quick-Check
Core Logic
The hash map stores sums of pairs from nums1 and nums2 as keys and their occurrence counts as values, enabling O(1) complement lookups.
State & Boundaries
Iterate over every element in nums1 and nums2 to cover all pair sums, ensuring completeness.
Common Pitfalls & Bugs
Forgetting to increment the count correctly or initializing counts improperly can lead to incorrect frequency tallies.
Accumulate counts of complementary sums from nums3 and nums4 pairs
| 12 | for c in nums3: |
| 13 | for d in nums4: |
| 14 | target = -(c + d) |
| 15 | if target in pair_count: |
| 16 | result += pair_count[target] |
Objective
To find and sum the counts of pairs from nums3 and nums4 whose negated sums exist in the precomputed hash map.
Key Insight
By iterating over all pairs from nums3 and nums4 and checking if the negated sum exists in the hash map, the algorithm efficiently counts all quadruples summing to zero. This leverages the precomputed frequencies to avoid redundant computations.
Interview Quick-Check
Core Logic
For each sum of pairs from nums3 and nums4, check if its negation exists in the hash map and add the corresponding frequency to the result.
State & Boundaries
Iterate over all pairs in nums3 and nums4 to ensure all possible complementary sums are considered.
Common Pitfalls & Bugs
Neglecting to negate the sum or failing to check the hash map before adding to the result can cause incorrect counts.
Return the total count of quadruples summing to zero
| 18 | return result |
Objective
To output the final count of all quadruples (i, j, k, l) where the sum of elements equals zero.
Key Insight
After accumulating counts from all complementary pairs, returning the result completes the solution. This final step delivers the answer computed efficiently by the previous steps.
Interview Quick-Check
Core Logic
Return the accumulated count representing the total number of quadruples summing to zero.
Line Analysis
This solution has 2 Critical lines interviewers watch for.
pair_count[pair_sum] = pair_count.get(pair_sum, 0) + 1
Increment the count of this sum in the hash map.
This line's placement and use of get with default zero ensures accurate frequency counting, which is fundamental to the algorithm's correctness and efficiency.
result += pair_count[target]
Add the frequency of the complementary sum to the result.
This line is critical because it aggregates the counts of all valid quadruples, directly contributing to the final answer.
pair_count = {}
Initialize a hash map to store sums of pairs from nums1 and nums2.
This data structure is essential for counting frequencies of pair sums, enabling constant-time lookups for complements later.
if target in pair_count:
Check if the negated sum exists in the hash map.
This conditional identifies whether there are pairs from nums1 and nums2 that complement the current pair to sum to zero.
pair_sum = a + b
Calculate the sum of the current pair from nums1 and nums2.
Computing the pair sum is the key step to building the frequency map of sums.
target = -(c + d)
Calculate the negated sum of the current pair from nums3 and nums4.
Negating the sum allows checking for complementary sums in the hash map that sum to zero with this pair.
return result
Return the total count of quadruples summing to zero.
Returning the accumulated result completes the algorithm, providing the final answer to the problem.
result = 0
Initialize the result counter to zero.
This variable accumulates the total count of quadruples that sum to zero, serving as the final output.
for a in nums1:
Iterate over each element in nums1.
This loop enumerates all possible first elements of pairs to be summed with elements from nums2.
for b in nums2:
Iterate over each element in nums2.
Nested iteration ensures all pairs from nums1 and nums2 are considered for sum calculation.
for c in nums3:
Iterate over each element in nums3.
This loop enumerates all possible first elements of pairs to be summed with elements from nums4 for complement checking.
for d in nums4:
Iterate over each element in nums4.
Nested iteration ensures all pairs from nums3 and nums4 are considered for complement sum calculation.
Test Your Understanding
Why does precomputing sums of pairs from two arrays and using a hash map reduce the problem from O(n^4) to O(n^2)?
Because it transforms the quadruple sum problem into two pair sum problems. By storing frequencies of sums from the first two arrays, the algorithm can find complements from the other two arrays in constant time per pair, avoiding the need to check all quadruples explicitly.
Related Problems
Hash Maps pattern
Don't just read it. Drill it.
Reconstruct 4Sum II from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.
Unlock the 4Sum II drill