๐๐ Two Pointer Techniques
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
- Find middle using slow-fast pattern
- Reverse second half of the list
- 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
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
- Find middle โ (covered)
- Find nth from end โ (covered)
- Check palindrome โ (covered)
- Remove nth from end โ (covered)
- Reorder list: L0โLnโL1โLn-1โL2โLn-2...
- Partition around value: All less than x before greater
- 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
- 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
- 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)
- 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!
Enjoying these tutorials?