Two Pointers

Two indices walking through one ordered structure, replacing a nested loop with a single pass.

5 min read
#algorithms
In one line

Walk two indices through ordered data, and at every step, discard the side that cannot improve the answer.

time O(n)space O(1)

A brute-force scan compares every pair, which costs O(n^2). Two pointers works because order carries information: if the structure is sorted (or has monotonic behaviour), one comparison tells you which side can never improve, so you can discard it forever.

That single decision — move left or move right — is the whole pattern. Each element is visited once, and nothing is ever revisited.

When to use it

Reach for it

  • The input is sorted, or you can sort it cheaply.
  • You are looking for a pair, triplet, or boundary that satisfies a condition.
  • You need to partition, dedupe, or compact in place with O(1) extra space.
  • You are comparing a sequence against itself from both ends (palindromes, reversals).

Skip it

  • Order is meaningless and cannot be created (use hashing instead).
  • You need every qualifying pair, not the existence of one — the discarded side may hide answers.
  • The condition is not monotonic, so shrinking one side does not reliably move you toward the target.
Signals in the problem statement
  • "sorted array" in the first sentence
  • "find two numbers that…" / "closest to target"
  • "in place" or "O(1) extra space"
  • "remove duplicates" or "move all X to the end"
  • "is it a palindrome"

The pattern

  1. 1

    Place pointers at the two ends (opposite direction) or both at the start (same direction).

  2. 2Evaluate the condition at the current pair.
  3. 3

    Move the pointer that cannot possibly improve the result.

  4. 4Stop when the pointers meet or cross.
@itsnas JavaScript
mainJavaScript
codeJavaScript
// Sorted array: does a pair sum to target?
function pairSum(nums, target) {
  let left = 0
  let right = nums.length - 1
 
  while (left < right) {
    const sum = nums[left] + nums[right]
    if (sum === target) return [left, right]
    if (sum < target) left++ // need a bigger value
    else right-- // need a smaller value
  }
 
  return null
}
fn pair_sum(nums: &[i32], target: i32) -> Option<(usize, usize)> {
    let (mut left, mut right) = (0, nums.len() - 1);
 
    while left < right {
        let sum = nums[left] + nums[right];
        if sum == target {
            return Some((left, right));
        } else if sum < target {
            left += 1;
        } else {
            right -= 1;
        }
    }
 
    None
}
std::optional<std::pair<int, int>> pairSum(
    std::vector<int>& nums, int target) {
  int left = 0, right = nums.size() - 1;
 
  while (left < right) {
    int sum = nums[left] + nums[right];
    if (sum == target) return {{left, right}};
    else if (sum < target) left++;
    else right--;
  }
 
  return std::nullopt;
}
main
Naseebullah
Ln 1, Col 1UTF-8JavaScript

Complexity

Time

Each element is visited at most once as the pointers close in.

Space

Just the two indices — no auxiliary structures.

Add O(nlogn)O(n \log n) up front if you have to sort the input yourself — that then dominates the total cost.

Common pitfalls

1

Forgetting the input must be ordered

The discard step is only valid under sorted or monotonic input. On unsorted data the pointers silently skip valid answers.

2

Off-by-one on the loop guard

Use left < right when a pair must be two distinct elements, and left <= right only when a single middle element is a valid answer.

3

Not skipping duplicates

In triplet and unique-pair problems, advance past equal neighbours after recording a hit, or the same answer repeats.

4

Moving both pointers at once

Unless the condition proves both sides are exhausted, moving both can step over the answer.

Variants worth knowing

  1. 1

    Opposite ends — pair sums, palindromes, container with most water.

  2. 2

    Fast and slow — cycle detection, middle of a linked list.

  3. 3Read and write — in-place dedupe and compaction.
  4. 4

    Sliding window — same-direction pointers with a running aggregate.

Practice, easiest first


Copyright © 2025-present itsnas.me 
All Rights Reserved.