Two Sum, 3Sum, and 4Sum
mediumTwo PointersHash MapSorting
Two Sum (LeetCode 1)
Using a Hash Map allows for finding the complement in O(1), leading to a total time complexity of O(n):
int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), i};
}
map.put(nums[i], i);
}
return new int[]{};
}
Variant: Two Sum II - Input Array Is Sorted (LeetCode 167): Use the two-pointer approach since the array is sorted.
int[] twoSumSorted(int[] numbers, int target) {
int l = 0, r = numbers.length - 1;
while (l < r) {
int sum = numbers[l] + numbers[r];
if (sum == target) return new int[]{l + 1, r + 1};
if (sum < target) l++;
else r--;
}
return new int[]{};
}
3Sum (LeetCode 15)
Sort the array first, then iterate with one fixed number and utilize the two-pointer technique for the remaining two numbers. Focus on skipping duplicates to ensure unique triplets.
List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue; // Deduplicate pivot
if (nums[i] > 0) break; // Optimization: sum can't be 0 if smallest is > 0
int l = i + 1, r = nums.length - 1;
while (l < r) {
int sum = nums[i] + nums[l] + nums[r];
if (sum == 0) {
res.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++; // Deduplicate left
while (l < r && nums[r] == nums[r - 1]) r--; // Deduplicate right
l++; r--;
} else if (sum < 0) l++;
else r--;
}
}
return res;
}
3Sum Closest (LeetCode 16)
int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closest = nums[0] + nums[1] + nums[2];
for (int i = 0; i < nums.length - 2; i++) {
int l = i + 1, r = nums.length - 1;
while (l < r) {
int sum = nums[i] + nums[l] + nums[r];
if (Math.abs(sum - target) < Math.abs(closest - target)) closest = sum;
if (sum < target) l++;
else if (sum > target) r--;
else return sum; // Found exact match
}
}
return closest;
}
4Sum (LeetCode 18)
Append another layer of iteration; the two-pointer logic remains the same.
List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < n - 3; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int l = j + 1, r = n - 1;
while (l < r) {
// Use long to avoid overflow when summing four numbers
long sum = (long) nums[i] + nums[j] + nums[l] + nums[r];
if (sum == target) {
res.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++; r--;
} else if (sum < target) l++;
else r--;
}
}
}
return res;
}
Note: Be careful with potential integer overflows in 4Sum; use
longfor the sum calculation.
Summary
| Problem | Technique | Time Complexity |
|---|---|---|
| Two Sum | Hash Map | O(n) |
| Two Sum II (Sorted) | Two Pointers | O(n) |
| 3Sum | Sorting + Two Pointers | O(n²) |
| 3Sum Closest | Sorting + Two Pointers | O(n²) |
| 4Sum | Sorting + Two Pointers | O(n³) |