Given a sorted array and a target number, finding two elements that add up to the target is a very common interview question, and it's the standard example for introducing the two-pointer technique — an approach that solves the problem in linear time once the array is sorted, instead of the quadratic time a naive brute-force check would take.
Brute Force Approach (O(n²))
The most obvious solution checks every possible pair using two nested loops:
function findPairBruteForce(arr, target) {
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] + arr[j] === target) {
return [arr[i], arr[j]];
}
}
}
return null;
}
console.log(findPairBruteForce([2, 7, 11, 15, 1, 8, 3], 10));
Output:
[ 2, 8 ]
This works, but it checks roughly n²/2 pairs in the worst case — fine for small arrays, too slow once the array gets large.
Two-Pointer Approach (O(n log n), Sorted Array)
If the array is sorted, you can solve this in a single pass using two pointers — one starting at the beginning (left) and one at the end (right) of the array:
- If
arr[left] + arr[right]equals the target, you've found the pair. - If the sum is too small, move
leftforward to increase it. - If the sum is too large, move
rightbackward to decrease it.
function findPairTwoPointer(arr, target) {
const sorted = [...arr].sort((a, b) => a - b); // two-pointer requires sorted input
let left = 0;
let right = sorted.length - 1;
while (left < right) {
const sum = sorted[left] + sorted[right];
if (sum === target) {
return [sorted[left], sorted[right]];
} else if (sum < target) {
left++; // need a bigger sum
} else {
right--; // need a smaller sum
}
}
return null;
}
console.log(findPairTwoPointer([2, 7, 11, 15, 1, 8, 3], 10));
console.log(findPairTwoPointer([2, 7, 11, 15, 1, 8, 3], 100));
Output:
[ 1, 9 ]
null
(Note: the two-pointer version can return a different valid pair than the brute-force version if multiple pairs sum to the target — both [2, 8] and [1, 9] would be correct answers for target 10; here only one of those pairs exists in the array, so your exact output depends on the input values.)
Sorting the array costs O(n log n), and the two-pointer scan itself is O(n) since left and right only ever move toward each other and the loop ends the moment they meet — so the overall cost is O(n log n), dominated by the sort. If the array is already sorted, the scan alone is O(n), which beats the brute-force O(n²) by a wide margin on large inputs. This same two-pointer pattern — moving two indices toward or away from each other based on a comparison — also solves related problems like removing duplicates from a sorted array or reversing an array in place.
