Used in: Merge Strings Alternately (LC 1768), Reverse Vowels of a String (LC 345), Reverse Words in a String (LC 151)
Time: usually O(n) | Space: usually O(1) extra

What is it?

Keep two index variables and move them through a string or array, instead of nested loops or making copies.

Two fingers on the data. Each finger moves by a rule. Stop when they meet or run out.

The shapes

1. Opposite ends (meet in the middle)

One pointer at the start, one at the end, moving toward each other.
Used for: reversing, palindromes, pair-sum on sorted input, Container With Most Water.

let l = 0, r = arr.length - 1;
while (l < r) {
  // compare or swap arr[l] and arr[r]
  l++;
  r--;
}

2. Read and write (slow / fast)

read checks every item. write marks where the next item you keep goes.
Used for: Move Zeroes, remove duplicates, squeezing extra spaces, in-place filtering.

let write = 0;
for (let read = 0; read < arr.length; read++) {
  if (keep(arr[read])) {
    arr[write] = arr[read];
    write++;
  }
}
// arr[0 .. write-1] is the result

3. Start and end of a chunk

One pointer marks where a word, window or run starts, the other finds where it ends.
Used for: finding words, runs of the same character, sliding windows.

let i = 0;
while (i < s.length) {
  while (i < s.length && s[i] === " ") i++; // skip separators
  const start = i;
  while (i < s.length && s[i] !== " ") i++; // find the end
  if (start < i) handle(s.slice(start, i));  // the chunk is s[start .. i-1]
}

4. Two sequences side by side

One pointer per input, each moving at its own pace.
Used for: merging, interleaving, Is Subsequence, comparing two lists.

let i = 0, j = 0;
while (i < a.length && j < b.length) {
  // take from a, b, or both, then advance whichever you used
}
// handle the leftover tail

Cues: when to reach for it

  • The input is a sequence (string or array).
  • The problem says reverse, palindrome or pair.
  • The input is sorted.
  • You need to find words, runs or windows.
  • You must remove or move items in place.
  • Two inputs processed together (merge, compare, interleave).
  • Brute force would be nested loops.
  • ⭐ Strongest cue: “in place” or “O(1) extra space”. Built-ins like split make new arrays. Pointers walk the data you already have.

How to build one yourself

  1. Solve a small example by hand.
  2. Notice which positions you were keeping track of.
  3. Each position → a pointer variable.
  4. Each “keep going until…” → a while loop.

Example, " the sky " read right to left: skip spaces, note where the word ends (y), keep going to the space before s, write down sky, repeat. You tracked “where the word ends” and “where I am now”. Those are the two pointers.

Gotchas

  • slice(start, stop) excludes stop → use end + 1 when end is the last character. See Reverse Words in a String (LC 151).
  • Every inner while needs the bounds check first: i >= 0 && s[i] .... Otherwise you read past the end.
  • Opposite ends: l < r vs l <= r matters. Ask whether the middle element needs handling.
  • Name pointers for what they mean (start, end, read, write), not p2.

Practice (LeetCode 75 Two Pointers section, in order)

  1. Move Zeroes (LC 283) → read and write
  2. Is Subsequence (LC 392) → two sequences
  3. Container With Most Water (LC 11) → opposite ends
  4. Max Number of K-Sum Pairs (LC 1679) → opposite ends on sorted input

Also: Reverse Vowels of a String (LC 345) → opposite ends