Problem
Given an array of integers and a target value, find any three numbers in the array whose sum is closest to the target and return that sum. You are guaranteed exactly one answer exists.
- Input:
nums = [-1, 2, 1, -4],target = 1 - Output:
2 - Explanation: The triplet
[-1, 2, 1]sums to 2, which is closer to 1 than any other triplet (e.g.[-1, -4, 2]sums to -3, which is 4 away).
Intuition
Once the array is sorted, you can fix one element and use two pointers converging from both ends of the remaining subarray. When the current sum is too small, advancing the left pointer increases it; when it's too large, retreating the right pointer decreases it. This lets you scan all meaningful triplets for a fixed outer element in O(n) instead of O(nยฒ), turning an O(nยณ) search into O(nยฒ).
Approach 1 โ Brute Force
Try every possible triplet and track the one whose sum is closest to the target.
- Initialize
closest_sumto the sum of the first three elements. - Use three nested loops over all distinct triples
(i, j, k)withi < j < k. - If
|current_sum - target|is smaller than|closest_sum - target|, updateclosest_sum. - Return
closest_sum.
1def threeSumClosest(nums: list[int], target: int) -> int:
2 n = len(nums)
3 closest_sum = nums[0] + nums[1] + nums[2]
4
5 for i in range(n - 2):
6 for j in range(i + 1, n - 1):
7 for k in range(j + 1, n):
8 current_sum = nums[i] + nums[j] + nums[k]
9 if abs(current_sum - target) < abs(closest_sum - target):
10 closest_sum = current_sum
11
12 return closest_sumTime: O(nยณ) โ three nested loops examine every distinct triplet. Space: O(1) โ only a constant number of variables are used.
Approach 2 โ Sort + Two Pointers
Sort the array, then fix each element as the first of the triplet and use two pointers on the remaining subarray. The sorted order guarantees that moving left right increases the sum and moving right left decreases it.
- Sort
nums. - Initialize
closest_sumto the sum of the first three elements. - For each index
ifrom0ton-3, setleft = i+1andright = n-1. - While
left < right, computecurrent_sum = nums[i] + nums[left] + nums[right].- If
current_sum == target, return immediately โ no triplet can be any closer. - If
|current_sum - target| < |closest_sum - target|, updateclosest_sum. - If
current_sum < target, incrementleft; otherwise decrementright.
- If
- Return
closest_sum.
1def threeSumClosest(nums: list[int], target: int) -> int:
2 nums.sort()
3 n = len(nums)
4 closest_sum = nums[0] + nums[1] + nums[2]
5
6 for i in range(n - 2):
7 left, right = i + 1, n - 1
8
9 while left < right:
10 current_sum = nums[i] + nums[left] + nums[right]
11
12 if current_sum == target:
13 return current_sum # exact match โ nothing can be closer
14
15 if abs(current_sum - target) < abs(closest_sum - target):
16 closest_sum = current_sum
17
18 if current_sum < target:
19 left += 1 # sum too small, advance left to increase it
20 else:
21 right -= 1 # sum too large, retreat right to decrease it
22
23 return closest_sumTime: O(nยฒ) โ sorting takes O(n log n); the two-pointer scan is O(n) per outer element over n elements. Space: O(log n) โ the in-place sort uses O(log n) stack space.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Brute Force | O(nยณ) | O(1) | Only for tiny arrays (n < 20) where code simplicity matters more than speed |
| Sort + Two Pointers | O(nยฒ) | O(log n) | All practical inputs; the standard interview solution |
Common Mistakes
- Forgetting to sort before using two pointers โ the rule "advance left to increase the sum" only holds when the array is sorted; on an unsorted array, any pointer move can change the sum in either direction unpredictably.
- Returning the minimum difference instead of the actual sum โ the problem asks for the closest sum value (e.g.,
2), not how far it is from the target (e.g.,1). - Initializing
closest_sumto0or infinity โ the initial value must be an actual triplet sum (e.g., the first three elements after sorting) so that the first distance comparison is meaningful;0can incorrectly dominate if the true closest sum is far from zero. - Using
i < j < kwith indices all starting at 0 โ the brute-force loops must enforce strict ordering; starting all three at 0 and adding!=guards is error-prone; nested range boundsrange(i+1, n-1)andrange(j+1, n)are cleaner. - Not short-circuiting on exact match โ skipping the early
returnwhensum == targetis not wrong, but it misses an easy optimization and signals a shallow understanding of the algorithm.
Related Problems
3sumโ the same sort + two-pointer framework, but finds all unique triplets that sum to exactly zerotwo-sum-ii-input-array-is-sortedโ the foundational two-pointer technique on a sorted array that this solution builds oncontainer-with-most-waterโ uses the same "converge from both ends" two-pointer strategy to maximize a different quantityboats-to-save-peopleโ another greedy two-pointer problem where pairing the current largest with the smallest drives the optimal solution