Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 5

Two-Pointer Technique for Sorted Arrays and Strings

Recommended resources

Welcome to the next stage of your journey! In our previous lessons, we built a solid foundation in complexity analysis, culminating in understanding amortized analysis. Now, we shift from analyzing algorithms to designing them using powerful, reusable patterns. This is where theory meets practice—a crucial step for your SDE interview preparation.

Today's lesson introduces the two-pointer technique, a remarkably efficient method for solving a wide range of problems involving arrays and strings. Your goal is to learn how to apply this technique, specifically the "Opposite Ends" pattern, to solve classic problems like "Two Sum on a Sorted Array" and "Valid Palindrome". Mastering this pattern will allow you to transform seemingly complex quadratic-time problems into linear-time solutions, demonstrating the kind of algorithmic thinking that top tech companies look for.

The Two-Pointer Technique: An Overview

At its core, the two-pointer technique involves using two integer indices (the "pointers") to traverse a data structure, typically an array or a string. By moving these pointers according to specific conditions, we can efficiently process the data and find a solution in a single pass.

There are a few common variations, but today we will focus on the Opposite Ends pattern. In this pattern, we initialize one pointer at the beginning of the data structure and another at the end. Then, we move them toward each other until they meet or cross.

This diagram illustrates the fundamental concept of the Opposite Ends pattern, with a 'left pointer' and a 'right pointer' moving towards the center of an array.

To get a formal introduction to this pattern and see a generic template in Java, let's turn to a helpful article.

Two Pointer Technique: Mastering the Opposite Ends Pattern

Please read the first part of this article from DEV.to.

Start by reading the introduction from the beginning down to the end of the section "What is the Opposite Ends Pattern?". Pay attention to the generic Java code template provided; it forms the basis for the solutions we'll build today.


Application 1: Two Sum on a Sorted Array

Let's apply this pattern to a classic interview problem: Two Sum. The problem is as follows: Given an array of sorted integers, find the indices of two numbers that add up to a specific target value.

A brute-force approach would be to use nested loops to check every possible pair of numbers. As you know from our complexity lessons, this would result in an time complexity. We can do much better. Since the array is sorted, it's a perfect candidate for the two-pointer technique.

The following video provides an excellent walkthrough, starting from the brute-force idea and progressively optimizing it to the linear-time two-pointer solution. This will help you understand why the two-pointer approach is so effective.

Visual introduction Two Pointer Algorithm | Data Structure and Algorithm for Coding Interviews

This video from Josh's DevBox provides a visual introduction to solving the Two Sum problem.

Watch the following segments: First, see the brute-force solution to understand the baseline. Next, watch the explanation of the optimal O(N) solution using two pointers. Finally, follow the live coding example, which walks through the pointer movements and logic step-by-step.

As the video demonstrated, the logic is elegant and efficient:

  1. Initialize a left pointer at index 0 and a right pointer at nums.length - 1.
  2. Calculate the sum: currentSum = nums[left] + nums[right].
  3. If currentSum equals the target, you've found the solution.
  4. If currentSum is less than the target, you need a larger sum. Since the array is sorted, the only way to achieve this is by moving the left pointer to the right (left++).
  5. If currentSum is greater than the target, you need a smaller sum. Move the right pointer to the left (right--).
  6. Repeat this process until left and right meet. If they meet without finding a solution, no such pair exists.

The image below visualizes this exact process.

A step-by-step demonstration of the two-pointer technique for the Two Sum problem. The pointers converge until their sum matches the target.

Now, let's look at a clean Java implementation of this logic.

Two Pointer Technique: Mastering the Opposite Ends Pattern

Return to the same article and review the "Two Sum (Sorted)" problem.

Find the code block for the TwoSumSorted class. Read through the implementation and the "Why it works" explanation that follows. Notice how it perfectly matches the logic we just discussed.

By using this technique, we've reduced the time complexity from to , as we only make a single pass through the array. The space complexity is since we only use a few variables to store the pointers.


Application 2: Valid Palindrome

The two-pointer technique isn't limited to sorted number arrays; it's also highly effective for string manipulation problems. Let's consider another classic: Valid Palindrome. The task is to check if a given string is a palindrome after converting all uppercase letters to lowercase and removing all non-alphanumeric characters.

For example, "A man, a plan, a canal: Panama" should return true because after cleaning, it becomes "amanaplanacanalpanama", which reads the same forwards and backwards.

The approach is straightforward:

  1. First, "clean" the input string by converting it to lowercase and removing any characters that are not letters or numbers. As a Java developer, you can achieve this using a StringBuilder or regex.
  2. Once you have the cleaned string, apply the two-pointer pattern. Place a left pointer at the start and a right pointer at the end.
  3. Compare the characters at the left and right pointers. If they are ever not the same, the string is not a palindrome.
  4. If the characters match, move the pointers one step closer to the center (left++, right--) and repeat until they meet.

Let's examine a practical implementation.

Two Pointer Technique: Mastering the Opposite Ends Pattern

Let's look at the next example in the article.

Find the code for the PalindromeValidator class. Observe how the code first creates a cleaned string and then applies the while (left < right) loop to perform the palindrome check.

This solution has a time complexity of , where is the length of the string, because both the cleaning process and the two-pointer check are linear operations. The space complexity is due to the storage needed for the cleaned string.


Conclusion

In this lesson, you've added a fundamental algorithmic pattern to your problem-solving toolkit. The two-pointer technique is a prime example of how choosing the right algorithm can lead to significant performance improvements—a skill that is heavily tested in SDE interviews.

Here are the key takeaways:

  • The two-pointer technique uses two indices to traverse a data structure, often in a single pass.
  • The Opposite Ends pattern is highly effective for problems on sorted arrays and strings, where you need to find pairs or check for symmetry.
  • It can reduce time complexity from a brute-force to an optimal .
  • The core logic for sorted arrays involves adjusting pointers based on whether the current pair's property (like a sum) is too small or too large.
  • The core logic for strings often involves checking for symmetrical properties by moving inward from both ends.

We've only scratched the surface of what two pointers can do. In our next lesson, we will explore another powerful variation of this idea: the sliding window technique, which is excellent for finding optimal subarrays or substrings.

To solidify your understanding, I recommend practicing with the "Beginner Level" problems listed in the "Practice Problems" section of the Two Pointer Technique: Mastering the Opposite Ends Pattern article you've been reading.