AlgoPlusAlgoPlus
Learn/Problem-Solving Patterns
Lesson

Two Pointers

On a sorted array, a left and right pointer converge — the pair's sum tells you which one to move, finding a target pair in a single pass.

7 min read Watch it move Build it

The two-pointers technique puts one marker at each end of a sorted array and walks them toward each other. Because the array is sorted, the current pair's sum tells you exactly which pointer to move: if the sum is too small you need a bigger value, so move the left pointer up; if it's too large you need a smaller value, so move the right pointer down. One linear pass replaces the nested loop a brute-force search would need.

Precondition: the array must be sorted
The whole 'move which pointer' decision depends on order. On an unsorted array, a small sum doesn't reliably mean 'move left up' — sort first (or use a hash set instead).

The loop, step by step

  1. 1Put lo at index 0 and hi at the last index.
  2. 2Look at arr[lo] + arr[hi].
  3. 3If it equals the target → you found the pair.
  4. 4If it's less than the target → move lo up to a larger value.
  5. 5If it's greater → move hi down to a smaller value.
  6. 6Stop when the pointers meet (lo >= hi) — no pair exists.

Worked trace — target 10 in [1, 3, 4, 6, 8, 10]

  1. 1lo=0(1), hi=5(10): 1 + 10 = 11 > 10 → move hi down.
  2. 2lo=0(1), hi=4(8): 1 + 8 = 9 < 10 → move lo up.
  3. 3lo=1(3), hi=4(8): 3 + 8 = 11 > 10 → move hi down.
  4. 4lo=1(3), hi=3(6): 3 + 6 = 9 < 10 → move lo up.
  5. 5lo=2(4), hi=3(6): 4 + 6 = 10found at indices 2 and 3.
Why each move is safe
When the sum is too large, the right value is the largest available — no smaller lo could rescue it, so arr[hi] can never be in any valid pair and is safely discarded. The mirror argument justifies moving lo up when the sum is too small.
function pairSum(arr, target) {
  let lo = 0, hi = arr.length - 1;
  while (lo < hi) {
    const sum = arr[lo] + arr[hi];
    if (sum === target) return [lo, hi];
    if (sum < target) lo++;   // need a bigger sum
    else hi--;                // need a smaller sum
  }
  return null; // no pair
}
// pairSum([1, 3, 4, 6, 8, 10], 10) === [2, 3]
OperationTimeSpace
Two pointers (sorted) · each pointer moves at most n steps totalO(n)O(1)
Brute force (all pairs) · checks every pairO(n²)O(1)
Check yourself
The pair's sum is larger than the target. Which pointer moves, and why?