Four Sum Problem All Unique Quadruplets in DSA Go - Time & Space Complexity
We want to understand how the time needed to find all unique sets of four numbers that add up to a target grows as the input list gets bigger.
How does the number of steps change when the list size increases?
Analyze the time complexity of the following code snippet.
func fourSum(nums []int, target int) [][]int {
sort.Ints(nums)
var res [][]int
n := len(nums)
for i := 0; i < n-3; i++ {
for j := i+1; j < n-2; j++ {
left, right := j+1, n-1
for left < right {
sum := nums[i] + nums[j] + nums[left] + nums[right]
if sum == target {
res = append(res, []int{nums[i], nums[j], nums[left], nums[right]})
left++
right--
} else if sum < target {
left++
} else {
right--
}
}
}
}
return res
}
This code finds all unique quadruplets in a sorted list that add up to the target value.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Nested loops and two-pointer traversal inside the innermost loop.
- How many times: Outer loop runs about n times, second loop about n times, and inner two-pointer loop runs up to n times in total.
As the input size grows, the number of steps grows roughly by the cube of the input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 1,000 steps |
| 100 | About 1,000,000 steps |
| 1000 | About 1,000,000,000 steps |
Pattern observation: When input size increases 10 times, operations increase about 1,000 times.
Time Complexity: O(n³)
This means the time needed grows roughly with the cube of the input size, so if the list doubles, the work increases eight times.
[X] Wrong: "The algorithm is O(n²) because it uses two loops and two pointers."
[OK] Correct: The two-pointer loop inside the nested loops still runs up to n times, making the total work about n x n x n, which is O(n³), not O(n²).
Understanding this time complexity helps you explain how nested loops and pointer techniques combine to affect performance, a skill useful in many coding challenges.
"What if we changed the problem to find unique triplets instead of quadruplets? How would the time complexity change?"
Practice
Four Sum Problem in data structures and algorithms?Solution
Step 1: Understand the problem statement
The Four Sum Problem asks to find all unique sets of four numbers in an array that add up to a specific target sum.Step 2: Identify the goal
The goal is not sorting or counting pairs but to find quadruplets that sum to the target without duplicates.Final Answer:
Find all unique quadruplets in an array that sum up to a target value -> Option DQuick Check:
Four Sum Problem = Find quadruplets summing to target [OK]
- Confusing with two or three sum problems
- Trying to sort only without finding quadruplets
- Counting pairs instead of quadruplets
Solution
Step 1: Understand data structure for quadruplets
We need a slice of slices of integers to store multiple quadruplets, each quadruplet is a slice of 4 ints.Step 2: Choose correct initialization
quadruplets := [][]int{} initializes an empty slice of int slices, suitable for storing multiple quadruplets. quadruplets := [4]int{} is a fixed array of 4 ints, not multiple quadruplets. quadruplets := make([]int, 4) is a slice of 4 ints, not a slice of quadruplets. quadruplets := map[int]int{} is a map, not suitable here.Final Answer:
quadruplets := [][]int{} -> Option AQuick Check:
Slice of int slices = [][]int{} [OK]
- Using fixed arrays instead of slices
- Using map instead of slice
- Initializing slice with wrong dimensions
nums := []int{1, 0, -1, 0, -2, 2}
target := 0
result := fourSum(nums, target)
fmt.Println(result)
// Assume fourSum is correctly implementedSolution
Step 1: Understand input and target
The input array is [1, 0, -1, 0, -2, 2] and target sum is 0.Step 2: Identify unique quadruplets summing to 0
Possible unique quadruplets are [-2, -1, 1, 2], [-2, 0, 0, 2], and [-1, 0, 0, 1]. These sum exactly to 0 and are unique.Final Answer:
[[-2 -1 1 2] [-2 0 0 2] [-1 0 0 1]] -> Option BQuick Check:
Sum quadruplets = 0 [OK]
- Including duplicate quadruplets
- Incorrect sums in quadruplets
- Missing some valid quadruplets
func fourSum(nums []int, target int) [][]int {
sort.Ints(nums)
var res [][]int
for i := 0; i < len(nums)-3; i++ {
for j := i + 1; j < len(nums)-2; j++ {
left, right := j+1, len(nums)-1
for left < right {
sum := nums[i] + nums[j] + nums[left] + nums[right]
if sum == target {
res = append(res, []int{nums[i], nums[j], nums[left], nums[right]})
left++
right--
} else if sum < target {
left++
} else {
right--
}
}
}
}
return res
}Solution
Step 1: Analyze duplicate handling
The code finds quadruplets but does not skip duplicates after finding a valid quadruplet, so duplicates appear in the result.Step 2: Check other parts
Sorting is correct, pointers are correctly initialized, and append usage is valid.Final Answer:
No checks to skip duplicate quadruplets causing duplicates in result -> Option AQuick Check:
Missing duplicate skip = duplicates in output [OK]
- Not skipping duplicates for i, j, left, right
- Incorrect pointer updates after finding quadruplet
- Assuming sorting alone removes duplicates
Solution
Step 1: Understand optimization goals
We want to reduce time complexity and avoid duplicates efficiently.Step 2: Evaluate approaches
Sort the array and use two nested loops with two pointers, skipping duplicates at each step is common but still O(n^3). Use four nested loops to check all quadruplets without sorting is brute force O(n^4). Sort the array and use a hash map to store sums of pairs, then find complements uses a hash map to store pair sums and find complements, reducing complexity and handling duplicates well. Use recursion without sorting or duplicate checks is inefficient without sorting or duplicate checks.Final Answer:
Sort the array and use a hash map to store sums of pairs, then find complements -> Option CQuick Check:
Hash map pairs + complements = optimized search [OK]
- Using brute force four loops
- Ignoring duplicate skipping
- Not sorting before processing
Ready to prove it?
Pass the test and this pattern moves unknown
