Interview Concept: Same Direction vs Opposite Direction Two Pointers

Understand the two core two pointer patterns — opposite-direction (converging) and same-direction (fast/slow or read/write) — with when to use each in interviews.

Overview

Almost every two pointer problem uses one of two patterns. Recognising which one applies is the fastest way to a clean solution in an interview.

1. Opposite-Direction (Converging) Pointers

One pointer starts at the beginning, the other at the end, and they move toward each other. This almost always needs a sorted array or a symmetric property.

  • Use when: searching for a pair/triplet with a target sum, checking palindromes, or maximising an area/width.
  • Key idea: the sorted order tells you which pointer to move to get closer to the goal.
  • Examples: Two Sum II, Valid Palindrome, Container With Most Water, 3Sum, Trapping Rain Water.

2. Same-Direction (Fast / Slow or Read / Write) Pointers

Both pointers start at (or near) the front and move the same way at different speeds or roles.

  • Read/Write: a fast pointer scans while a slow pointer writes kept values — used for in-place filtering.
  • Fast/Slow (speed): one pointer moves twice as fast — used on linked lists for cycles and middles.
  • Examples: Remove Element, Move Zeroes, Remove Duplicates, Linked List Cycle, Middle of the List.

How to Choose

Signal in the problemLikely pattern
Array is sorted; looking for a pair/sumOpposite-direction
In-place removal / compactionSame-direction read/write
Linked list cycle or middleSame-direction fast/slow
Longest/shortest window with a constraintSame-direction sliding window

Code Templates

Pattern 1 — Opposite-Direction (Converging)

Python

left, right = 0, len(arr) - 1
while left < right:
    # use arr[left] and arr[right]
    if condition:
        left += 1
    else:
        right -= 1

Java

int left = 0, right = arr.length - 1;
while (left < right) {
    // use arr[left] and arr[right]
    if (condition) left++;
    else right--;
}

C++

int left = 0, right = (int)arr.size() - 1;
while (left < right) {
    // use arr[left] and arr[right]
    if (condition) left++;
    else right--;
}

Pattern 2 — Same-Direction (Read / Write)

Python

slow = 0
for fast in range(len(arr)):
    if keep(arr[fast]):
        arr[slow] = arr[fast]
        slow += 1
# slow = length of the kept prefix

Java

int slow = 0;
for (int fast = 0; fast < arr.length; fast++) {
    if (keep(arr[fast])) arr[slow++] = arr[fast];
}
// slow = length of the kept prefix

C++

int slow = 0;
for (int fast = 0; fast < (int)arr.size(); fast++) {
    if (keep(arr[fast])) arr[slow++] = arr[fast];
}
// slow = length of the kept prefix

Key Takeaways

  • First ask: are the pointers converging or moving together?
  • Opposite-direction usually needs sorting; same-direction usually does not.
  • Both patterns turn many O(n^2) brute forces into O(n).
Written by Lorens Mishra

Software Engineer Notes Management System Administrator

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.