AlgoMaster Logo

Introduction to Two Pointers

Ashish

Ashish Pratap Singh

Two Pointers is a powerful problem-solving pattern where you initialize two variables and move them towards each other, away from each other, or in the same direction, based on the problem.

Using this approach, you can reduce the time complexity of many array and string related problems from O(n²) to O(n).

In this chapter, I’ll break down:

  • what the Two Pointers pattern is
  • types of two pointers
  • and when to use it

What is the Two Pointers pattern?

Let's first understand what a pointer is.

A pointer is simply a variable that represents an index or position within a data structure, such as an array or linked list.

0
1
1
2
pointer
2
3
3
4
4
5

Using pointers at different positions, we can efficiently compare elements and make decisions without relying on nested loops, which would otherwise lead to O(n²) time complexity.

The Two Pointers technique can be applied in different ways depending on the problem.

Let’s explore the three most common strategies.

1. Converging Pointers

In this approach, pointers start at opposite ends of a data structure and move inward toward each other.

0
1
start
1
2
2
3
3
4
4
5
end

The pointers adjust their positions based on comparisons, until a certain condition is met, or they cross each other.

This strategy is ideal for problems where we need to compare elements from opposite ends of an array or string for example: checking if a string is a palindrome

A palindrome is a word, phrase, or sequence that reads the same forward and backward (e.g., "racecar", "madam").

To check if a string is a palindrome, we:

Initialize two pointers: one at the beginning and one at the end.

Compare characters at both pointers:

  • If they match, move both pointers inward.
  • If they don’t match, return false.

Repeat until the pointers meet.

2. Parallel Pointers

In this approach, both pointers start at the same end (usually the beginning) and move in the same direction.

0
1
first
1
2
second
2
3
3
4
4
5

These pointers generally serve two different but complementary roles:

  • the right pointer is used to explore or find new information.
  • and the left pointer is used to track progress or maintain constraints.

Here are the two popular variations of this approach:

  • Sliding Window Technique: In this approach, two pointers slide across an array or string while maintaining a dynamic range. It’s commonly used to find subarrays or substrings that meet specific criteria, such as:
    • Finding the longest substring without repeating characters
    • or Finding the smallest subarray with a given sum
  • Fast and Slow Pointers: This involves two pointers moving at different speeds. It’s commonly used to detect cycles in linked lists or find the middle node of a linked list.

3. Trigger-Based Pointers

In this approach, we move the first pointer independently until it finds an element that meets a certain condition.

After this, we start traversing with the second pointer to find additional information related to what the first pointer found.

This technique is particularly useful when we need to process elements in stages or maintain a fixed distance between two pointers.

A good example of this approach is finding the Nth node from the end of a linked list.

  • We move the first pointer n steps forward
  • Once the first pointer reaches the Nth node, initialize the second pointer at the head.
  • Move both pointers one step at a time until the first pointer reaches the end.
  • At this point, the second pointer will be at the Nth node from the end.

When to use two pointers pattern?

A Two-Pointer algorithm is generally applied to linear data structures, such as: array, strings or linked lists.

A strong clue that a problem can be solved using the Two Pointers technique is if the input data follows a predictable pattern—such as sorted array or palindromic string.

For example, in a sorted array, moving a pointer to the right ensures you are always moving to a greater or equal value, making it easy to compare the values at both the pointers.

Another strong indicator that a problem can be solved using Two Pointers is when it explicitly asks for:

  • A pair of values that satisfy a condition
  • or A result that can be generated from two values