Skip to main content

Two Pointers

Concept

The Two Pointers pattern uses two index variables that move through the array (or string) โ€” either toward each other (opposite direction) or in the same direction (fast/slow pointers).

It eliminates the need for nested loops, reducing O(nยฒ) brute-force solutions to O(n).


When to Use

  • The array/string is sorted (or sorting it first is allowed)
  • You're looking for pairs or triplets that satisfy a condition
  • You need to partition or remove elements in-place
  • The problem mentions "two numbers that sum to target"
  • Detecting cycles in a linked list (fast/slow pointer variant)

Types of Two Pointers

Type 1: Opposite Direction (Converging)

[1, 2, 3, 4, 5, 6]
โ†‘ โ†‘
left right

Both pointers start at opposite ends and move inward.

Type 2: Same Direction (Fast & Slow)

[1, 2, 3, 4, 5, 6]
โ†‘ โ†‘
slow fast

One pointer runs ahead; the slow pointer marks where valid elements go.


Java Template

// ---- Type 1: Converging (sorted array) ----
public boolean hasPairWithSum(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) return true;
else if (sum < target) left++;
else right--;
}
return false;
}

// ---- Type 2: Fast/Slow (remove duplicates in-place) ----
public int removeDuplicates(int[] nums) {
int slow = 0;
for (int fast = 1; fast < nums.length; fast++) {
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1; // new length
}

// ---- Type 3: Expanding Around Center (Palindromes) ----
private int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
return right - left - 1; // length of the palindrome
}

Worked Example 1: 3Sum

Problem: Find all unique triplets in an unsorted array that sum to zero.

Approach:

  1. Sort the array โ†’ enables two-pointer on the inner pair
  2. For each element nums[i], use two pointers for the remaining subarray
  3. Skip duplicates to avoid repeated triplets
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();

for (int i = 0; i < nums.length - 2; i++) {
// Skip duplicate values for the first element
if (i > 0 && nums[i] == nums[i - 1]) continue;

int left = i + 1, right = nums.length - 1;

while (left < right) {
int sum = nums[i] + nums[left] + nums[right];

if (sum == 0) {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
// Skip duplicates for left and right
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return result;
}

Trace for [-1, 0, 1, 2, -1, -4]:

After sort: [-4, -1, -1, 0, 1, 2]

i=0 (โˆ’4): left=1, right=5 โ†’ sum=โˆ’4+(โˆ’1)+2=โˆ’3 < 0 โ†’ left++
left=2, right=5 โ†’ sum=โˆ’4+(โˆ’1)+2=โˆ’3 < 0 โ†’ left++
left=3, right=5 โ†’ sum=โˆ’4+0+2=โˆ’2 < 0 โ†’ left++
left=4, right=5 โ†’ sum=โˆ’4+1+2=โˆ’1 < 0 โ†’ left++
left=5 โ‰ฅ right โ†’ stop

i=1 (โˆ’1): left=2, right=5 โ†’ sum=โˆ’1+(โˆ’1)+2=0 โœ“ โ†’ add [โˆ’1,โˆ’1,2]
skip dup for left, right โ†’ left=3, right=4
sum=โˆ’1+0+1=0 โœ“ โ†’ add [โˆ’1,0,1]

i=2 (โˆ’1): skip (dup of i=1)
...
Result: [[-1,-1,2], [-1,0,1]]

Time: O(nยฒ) | Space: O(1) (ignoring output)


Worked Example 2: Longest Palindromic Substring (Expand Around Center)

Problem: Find the longest contiguous palindromic substring in s.

Approach:

  1. Every palindrome mirrors around its center. A string of length nn has 2nโˆ’12n - 1 centers (single characters for odd lengths, gaps between characters for even lengths).
  2. For each center, expand outward as long as characters match.
public String longestPalindrome(String s) {
if (s == null || s.isEmpty()) return "";
int start = 0, maxLen = 1;

for (int i = 0; i < s.length(); i++) {
int len1 = expand(s, i, i); // odd length palindrome (center: i)
int len2 = expand(s, i, i + 1); // even length palindrome (center: i, i+1)
int len = Math.max(len1, len2);

if (len > maxLen) {
maxLen = len;
start = i - (len - 1) / 2;
}
}
return s.substring(start, start + maxLen);
}

private int expand(String s, int l, int r) {
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
l--;
r++;
}
return r - l - 1;
}

Time: O(nยฒ) | Space: O(1)


Common Mistakes

MistakeFix
Not sorting firstSort when using converging two pointers
Off-by-one: left < right vs left <= rightUse < for pairs, <= only when single element is valid
Missing duplicate skipAfter finding a result, advance past all duplicates
Forgetting inner loop advancesBoth left++ AND right-- after a match

LeetCode Problems

Easy

#ProblemType
125Valid PalindromeConverging
167Two Sum II - Input Array is SortedConverging
283Move ZeroesFast/Slow
344Reverse StringConverging
977Squares of a Sorted ArrayConverging

Medium

#ProblemType
11Container With Most WaterConverging
153SumSort + converging
163Sum ClosestSort + converging
184SumSort + two loops + converging
75Sort Colors3-way partition (Dutch flag)
80Remove Duplicates IIFast/Slow
142Linked List Cycle IIFast/Slow on list
986Interval List IntersectionsTwo list pointers

Hard

#ProblemType
42Trapping Rain WaterConverging with max tracking
76Minimum Window SubstringSliding window variant
๐Ÿ“–
Track Page Progress0 / 635 Read
Knowledge Base Completion0%