Step 1 Understand it
Remember it by
Sorted? Start at both ends and walk inwards — each move throws away an impossible answer.
Watch it happen
Read the animation as text
- The array is sorted. Put L on the smallest number and R on the largest.
- 1 + 11 = 12: too big. L already holds the smallest number left, so 11 is too big with every partner. Drop it: move R left.
- 1 + 8 = 9: too small. R already holds the largest number left, so 1 is too small with every partner. Drop it: move L right.
- 2 + 8 = 10. Answer (1-indexed): [2, 5]. Each step threw away a number that could never be in the answer, so it is one pass and O(1) space.
The idea
Two indexes move through the data at the same time, usually one from each end. Each comparison tells you which pointer can move, so you rule out many answers per step and finish in one pass.
Picture it
flowchart LR
L["L →"] --- A["sorted array"] --- R["← R"]
A --> Q{"compare arr[L] and arr[R]"}
Q -->|"too small"| ML["move L right"]
Q -->|"too big"| MR["move R left"]
Q -->|"just right"| D["answer ✓"]Analogy
Finding two friends whose heights add to 3 metres in a line sorted by height. Too short in total? Swap the shortest for the next one up. Too tall? Swap the tallest for the next one down.
Where the analogy breaks
With friends you could just look around. The trick only works because the order is known: moving a pointer is safe only when sorting guarantees everything you skip is worse.
More detail
What it is
Imagine you and a friend are searching a library. Instead of you searching the whole library alone, you start at the front door, and your friend starts at the back door. You walk towards each other until you meet in the middle. That's the Two Pointer technique! It's a strategy where you use two variables (pointers) to iterate through an array or string simultaneously, usually from opposite ends or moving at different speeds.
When to use it
- When dealing with sorted arrays or string palindromes.
- When searching for pairs that sum up to a target (if sorted).
- When reversing an array or string completely in-place.
How it works
You initialize a left pointer at index 0, and a right pointer at the last index. You run a while (left < right) loop. Depending on the condition, you either move the left pointer forward left++ or the right pointer backward right-- until they meet.
Example walkthrough
Input: s = "racecar"
- left='r', right='r'. They match. Move pointers inward (left++, right--).
- left='a', right='a'. They match. Move inward.
- left='c', right='c'. They match.
- left and right cross paths at 'e'. It's a valid Palindrome!
Result: true
Related patterns
- Sliding Window: A variation of Two Pointers where the pointers move in the same direction.
Step 2 Recognise it
Words that signal it
- The input is sorted (or sorting it is allowed)
- 'Pair / triplet that sums to…' in a sorted array
- 'Palindrome', 'reverse in place'
- 'Container', 'trapping water' — two walls that limit each other
- They ask for O(1) extra space
Don't confuse it with
- Sliding Window: Window = a contiguous range where both pointers move the same way. Two pointers here = opposite ends moving towards each other.
- Arrays & Hashing: Unsorted and you can't sort (you need original indexes)? Use a hash map instead.
Gut check
Sorted, and I'm comparing a pair from both ends? → two pointers.
How to recognise it in an interview
The array is explicitly SORTED, or you need to find a combination of elements at opposite ends.
Step 3 The template
The general shape. Adapt it to each problem rather than learning one solution per problem.
def solve(arr):
left, right = 0, len(arr) - 1
while left < right:
if ...: # found what you want
return ...
elif ...: # left side too small / worse
left += 1
else: # right side too big / worse
right -= 1
return ...The same template in Java
class Solution {
public boolean isPalindrome(String s) {
int left = 0, right = s.length() - 1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}Common mistakes
- Using left <= right when the two pointers must be different items (it should be left < right).
- In 3Sum, not skipping repeated values, so the same triplet appears twice.
- Moving the wrong pointer in Container With Most Water: always move the shorter wall, because the taller one can't help while the shorter one limits the height.
- Forgetting to actually increment or decrement the pointers inside the loop, causing an infinite loop crash!
Step 4 Watch it run
Two problems, traced step by step exactly as the code runs.
Easy example: Two Sum II (sorted input)
Input: numbers = [1, 2, 4, 6, 8, 11], target = 10
| L | R | sum | action |
|---|---|---|---|
| 0 | 5 | 1 + 11 = 12 | too big → move R left |
| 0 | 4 | 1 + 8 = 9 | too small → move L right |
| 1 | 4 | 2 + 8 = 10 | found it |
Result: [2, 5]
Notice: When the sum is too big, L already holds the smallest number left, so R is too big with every partner. R can never be in the answer — move it.
def two_sum_sorted(numbers, target):
left, right = 0, len(numbers) - 1
while left < right:
total = numbers[left] + numbers[right]
if total == target:
return [left + 1, right + 1] # 1-indexed answer
if total < target:
left += 1
else:
right -= 1
return []Medium example: Container With Most Water
Input: height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
| L | R | area | best | move |
|---|---|---|---|---|
| 0 (h=1) | 8 (h=7) | min(1, 7) × 8 = 8 | 8 | move L (shorter) |
| 1 (h=8) | 8 (h=7) | min(8, 7) × 7 = 49 | 49 | move R (shorter or equal) |
| 1 (h=8) | 7 (h=3) | min(8, 3) × 6 = 18 | 49 | move R (shorter or equal) |
| 1 (h=8) | 6 (h=8) | min(8, 8) × 5 = 40 | 49 | move R (shorter or equal) |
| 1 (h=8) | 5 (h=4) | min(8, 4) × 4 = 16 | 49 | move R (shorter or equal) |
| 1 (h=8) | 4 (h=5) | min(8, 5) × 3 = 15 | 49 | move R (shorter or equal) |
| 1 (h=8) | 3 (h=2) | min(8, 2) × 2 = 4 | 49 | move R (shorter or equal) |
| 1 (h=8) | 2 (h=6) | min(8, 6) × 1 = 6 | 49 | move R (shorter or equal) |
Result: 49
Notice: The shorter wall decides the height. Moving the taller wall can only shrink the width without raising the height, so always move the shorter one.
def max_area(height):
left, right = 0, len(height) - 1
best = 0
while left < right:
area = min(height[left], height[right]) * (right - left)
best = max(best, area)
if height[left] < height[right]:
left += 1
else:
right -= 1
return bestStep 5 Practise
Read each question and say the pattern and the trick out loud before you open the answer. Then solve it on LeetCode. Tick a problem once you've solved it on your own: it comes back for review tomorrow, then after 3, 7, 14 and 30 days, then every month, on the DSA page.
Easy
-
Valid Palindrome Easy
Decide whether a string reads the same forwards and backwards, ignoring case and non-letters.
Show answer
Technique: Two pointers from both ends
The clue: 'Palindrome' = compare the two ends moving inwards.
The trick: Skip non-alphanumeric characters with each pointer, compare lower-case letters, move both inwards.
Medium
-
In a sorted array, find the two numbers that add up to a target, using constant extra space.
Show answer
Technique: Two pointers from both ends
The clue: Sorted + a pair + O(1) space.
The trick: Sum too small → move the left pointer right; too big → move the right pointer left.
-
3Sum Medium
Find all unique triplets that add up to zero.
Show answer
Technique: Sort + fix one + two pointers
The clue: A triplet sum is a pair sum (Two Sum II) for every fixed first number.
The trick: Sort; for each i, run two pointers on the rest for −nums[i]; skip equal neighbours to avoid duplicate triplets.
-
Container With Most Water Medium
Pick two vertical lines that, with the x-axis, hold the most water.
Show answer
Technique: Two pointers, move the shorter wall
The clue: Two walls limit each other: area = shorter height × distance.
The trick: Start at both ends and always move the shorter wall; moving the taller one can never help.
Hard
-
Trapping Rain Water Hard
Given bar heights, compute how much rain water is trapped between them.
Show answer
Technique: Two pointers with left max and right max
The clue: Water above a bar depends on the tallest bar on each side.
The trick: Water at i = min(max left, max right) − height[i]; move the side with the smaller max, since that side is the limit.
What to say in the interview
'Since the array is sorted, we can avoid O(N) extra space by using two pointers from opposite ends.'
Follow-up prep
What if there are duplicates in the sorted array? (You might have to skip them).