Home / Patterns / Lesson 1

Two Pointers — The Pattern That Kills O(n²)

Easy ⏱ 6 min read 🧩 Pattern 1 of 16

Two pointers replaces a nested loop with two indexes moving intelligently through the data — O(n²) becomes O(n). It comes in two flavours.

Flavour 1: Converging pointers (sorted data)

Start one pointer at each end; move them toward each other based on a comparison.

// Pair with target sum in a SORTED array
function pairSum(nums, target) {
  let lo = 0, hi = nums.length - 1;
  while (lo < hi) {
    const sum = nums[lo] + nums[hi];
    if (sum === target) return [lo, hi];
    if (sum < target) lo++;      // need bigger → move left pointer right
    else hi--;                    // need smaller → move right pointer left
  }
  return [-1, -1];
}

Why it works: sorting gives you information. If the sum is too small, only moving lo right can increase it — you safely skip every pair you never checked.

Flavour 2: Reader/writer pointers (in-place edits)

One pointer reads every element; the other writes only the elements you keep.

// Move all zeroes to the end, in place
function moveZeroes(nums) {
  let write = 0;
  for (let read = 0; read < nums.length; read++) {
    if (nums[read] !== 0) nums[write++] = nums[read];   // keep it
  }
  while (write < nums.length) nums[write++] = 0;        // fill the rest
  return nums;
}

Spot it when…

  • The array is sorted (or you can sort it) and you need pairs/triplets.
  • You must edit in place without extra space (remove duplicates, partition).
  • Palindrome checks — compare from both ends inward.

Practice now on the judge

Complexity: O(n) time, O(1) space — say both in the interview. Next: Sliding Window, two pointers' famous cousin.