Web Analytics

๐Ÿ“๐Ÿ“ Two Pointer Techniques

Intermediate ~20 min read โญ Essential Pattern

Two pointers are THE fundamental technique for linked list problems. Master two patterns: slow-fast (different speeds) and gap (same speed, different start). These patterns solve 90% of linked list interview questions in O(1) space!

๐ŸŽฏ Interview Alert!

Two-pointer patterns appear EVERYWHERE:

  • โœ… Find middle - Asked by Google, Amazon, Microsoft
  • โœ… Nth from end - Top interview question
  • โœ… Palindrome check - Facebook, LinkedIn favorite
  • โœ… Remove duplicates - Common follow-up
  • โœ… Reorder list - Advanced variation

Master these patterns and you'll ace linked list interviews!

The Two Patterns

Pattern 1: Slow-Fast (Different Speeds)

slow = head  # Moves 1 step
fast = head  # Moves 2 steps

while fast and fast.next:
    slow = slow.next      # 1 step
    fast = fast.next.next # 2 steps

# When fast reaches end, slow is at middle!

Use for: Find middle, Detect cycle, Palindrome check

Pattern 2: Gap (Same Speed, Different Start)

# Move first pointer n steps ahead
first = head
for i in range(n):
    first = first.next

# Move both together
second = head
while first:
    first = first.next
    second = second.next

# When first reaches end, second is nth from end!

Use for: Nth from end, Remove nth from end

See Them in Action

Watch both patterns work:

Pattern 1: Find Middle (Slow-Fast)

The slow-fast pattern is elegant: when the fast pointer reaches the end, the slow pointer is exactly at the middle!

Why It Works

The logic:

  • Fast moves twice as fast as slow
  • When fast travels distance D, slow travels D/2
  • When fast reaches end (distance = n), slow is at n/2 (middle!)

Step-by-Step Example

List: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5

Step 0: Both at 1

slow=1, fast=1

Step 1: Slow moves to 2, Fast moves to 3

slow=2, fast=3

Step 2: Slow moves to 3, Fast moves to 5

slow=3, fast=5

Result: Fast reached end, slow is at middle (3)!

Pattern 2: Nth from End (Gap)

The gap pattern maintains a fixed distance between two pointers. When the first reaches the end, the second is exactly n positions from the end!

Why It Works

The logic:

  • Create gap of n by moving first pointer n steps
  • Move both pointers together - gap stays constant!
  • When first reaches end, second is n behind (n from end!)

Step-by-Step Example

List: 1 โ†’ 2 โ†’ 3 โ†’ 4 โ†’ 5 โ†’ 6

Find: 2nd from end

Phase 1: Move first 2 steps ahead

first=1 โ†’ first=2 โ†’ first=3
second=1 (hasn't moved yet)

Phase 2: Move both together

first=3, second=1
first=4, second=2
first=5, second=3
first=6, second=4
first=null, second=5

Result: Second is at 5 (2nd from end)!

Application: Palindrome Check

Combine slow-fast with reversal to check if a list is a palindrome - all in O(1) space!

The 3-Step Algorithm

  1. Find middle using slow-fast pattern
  2. Reverse second half of the list
  3. Compare first half with reversed second half
# Step 1: Find middle
slow = fast = head
while fast and fast.next:
    slow = slow.next
    fast = fast.next.next

# Step 2: Reverse second half
prev = None
while slow:
    next_node = slow.next
    slow.next = prev
    prev = slow
    slow = next_node

# Step 3: Compare
while prev:
    if head.data != prev.data:
        return False
    head = head.next
    prev = prev.next

return True

The Complete Code

Output
Click Run to execute your code

Complexity Analysis

Operation Time Space Pattern
Find middle O(n) โœ“ O(1) โœ“โœ“ Slow-Fast
Find nth from end O(n) โœ“ O(1) โœ“โœ“ Gap
Check palindrome O(n) โœ“ O(1) โœ“โœ“ Slow-Fast + Reverse
Remove nth from end O(n) โœ“ O(1) โœ“โœ“ Gap
Find intersection O(m+n) โœ“ O(1) โœ“โœ“ Align + Move

Common Mistakes

โŒ Mistake #1: Not Checking fast.next

# WRONG - crashes on odd-length lists!
while fast:
    fast = fast.next.next  # Crashes if fast.next is null!

# RIGHT - check both
while fast and fast.next:
    fast = fast.next.next  # Safe!

โŒ Mistake #2: Wrong Gap Size

# WRONG - off by one!
for i in range(n):  # Creates gap of n
    first = first.next

# For removing nth from end, need gap of n+1
for i in range(n + 1):  # Creates gap of n+1
    first = first.next

โŒ Mistake #3: Calculating Length First

# WRONG - two passes, less elegant
length = get_length(head)
middle_idx = length // 2
# ... traverse to middle_idx

# RIGHT - one pass with two pointers!
slow = fast = head
while fast and fast.next:
    slow = slow.next
    fast = fast.next.next
# slow is at middle!

Interview Variations

Common Follow-ups

  1. Find middle โœ“ (covered)
  2. Find nth from end โœ“ (covered)
  3. Check palindrome โœ“ (covered)
  4. Remove nth from end โœ“ (covered)
  5. Reorder list: L0โ†’Lnโ†’L1โ†’Ln-1โ†’L2โ†’Ln-2...
  6. Partition around value: All less than x before greater
  7. Split into k parts: Divide list into k equal parts

Interview Tips

๐Ÿ’ก How to Ace Two-Pointer Questions

  • โœ… Identify the pattern: Different speeds or gap?
  • โœ… Draw it out: Visualize pointer movements
  • โœ… Explain O(1) space: Key advantage over arrays!
  • โœ… Handle edge cases: Empty, single node, even/odd length
  • โœ… Check fast.next: Avoid null pointer errors
  • โœ… Know both patterns: When to use each

โœ… Pattern Selection Guide

  • Use Slow-Fast when: Need middle, detect cycle, or split in half
  • Use Gap when: Need nth from end or remove nth from end
  • Combine patterns when: Checking palindrome, reordering list

Real-World Applications

Where Are These Used?

  • Music players: Finding middle of playlist
  • Undo/Redo: Navigating history n steps back
  • Text editors: Finding center of document
  • Network protocols: Sliding window algorithms
  • Data validation: Palindrome checking

Summary

Two-Pointer Mastery

  1. Slow-Fast Pattern: Different speeds (1 vs 2 steps)
    • Find middle: When fast reaches end, slow at middle
    • Detect cycle: If they meet, cycle exists
  2. Gap Pattern: Same speed, different start
    • Nth from end: Create gap of n, move together
    • Remove nth: Create gap of n+1 (for previous node)
  3. All O(n) time, O(1) space: Optimal solutions!

Interview tip: Two pointers are more elegant than calculating length. Always check fast.next to avoid crashes. Draw the pointers moving to visualize!

What's Next?

You've mastered two-pointer techniques! Next: Doubly Linked Lists - bidirectional traversal with prev pointers!

Practice: Implement all 5 operations. Try the variations. Draw pointer movements on paper!