• Home
  • About
    • Thoughts To Pen photo

      Thoughts To Pen

      My thoughts on Computer Programming || Psychology || Personal Finances || & much more...

    • Learn More
    • Twitter
    • Instagram
    • Github
    • StackOverflow
  • Posts
    • All Posts
    • All Tags
  • Projects
  • Portfolio
  • Resources
  • About

Two Pointer Technique

09 Feb 2026

Introduction

After learning Binary Search, you saw how narrowing the search space dramatically improves performance. The Two Pointer technique applies a similar idea — but instead of halving the search space, we use two pointers that move through the data from different positions, eliminating unnecessary comparisons.

This technique can transform a brute-force $O(n^2)$ solution (with nested loops) into a clean $O(n)$ solution.


Two Main Patterns

Pattern 1: Opposite-Direction Pointers

Two pointers start at opposite ends of a sorted array and move toward each other.

[1, 3, 5, 7, 11, 15]
 ^                  ^
left              right

Use for: Finding pairs that satisfy a condition (e.g., two numbers that add up to a target).

Pattern 2: Same-Direction Pointers (Fast & Slow)

Two pointers start at the same end but move at different speeds.

[0, 0, 1, 1, 1, 2, 2, 3]
 ^
slow
 ^
fast

Use for: Removing duplicates, partitioning arrays, detecting cycles in linked lists.


Problem 1: Two Sum on a Sorted Array

Given: A sorted array and a target sum. Find: Two numbers that add up to the target.

Brute-Force Approach — $O(n^2)$

// Check every pair — nested loops
for (int i = 0; i < arr.length; i++) {
    for (int j = i + 1; j < arr.length; j++) {
        if (arr[i] + arr[j] == target) return new int[]{i, j};
    }
}

Two Pointer Approach — $O(n)$

Since the array is sorted, we can do much better:

  1. Place left at index 0 and right at the last index.
  2. Calculate sum = arr[left] + arr[right].
  3. If sum == target, we found the answer.
  4. If sum < target, move left forward (we need a bigger number).
  5. If sum > target, move right backward (we need a smaller number).

Walkthrough

Find two numbers in [2, 7, 11, 15, 20] that add up to 22.

Step left right arr[left] arr[right] Sum Action
1 0 4 2 20 22 ✅ Found!

That was quick. Let’s try target 26.

Step left right arr[left] arr[right] Sum Action
1 0 4 2 20 22 22 < 26 → move left
2 1 4 7 20 27 27 > 26 → move right
3 1 3 7 15 22 22 < 26 → move left
4 2 3 11 15 26 ✅ Found!

Java Implementation

public class TwoSumSorted {

    /**
     * Finds two indices in a sorted array whose values sum to the target.
     * Uses opposite-direction two pointers.
     *
     * @return array of two indices, or empty array if no solution exists
     */
    public static int[] twoSum(int[] sortedArr, int target) {
        int left = 0;
        int right = sortedArr.length - 1;

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

            if (sum == target) {
                return new int[]{left, right};
            } else if (sum < target) {
                left++;   // we need a bigger sum → move left pointer forward
            } else {
                right--;  // we need a smaller sum → move right pointer backward
            }
        }

        return new int[]{}; // no pair found
    }

    public static void main(String[] args) {
        int[] arr = {2, 7, 11, 15, 20};
        int[] result = twoSum(arr, 26);
        System.out.println(result[0] + ", " + result[1]); // Output: 2, 3
    }
}

Why does this work? Because the array is sorted:

  • If the sum is too small, increasing left can only increase the sum.
  • If the sum is too large, decreasing right can only decrease the sum.
  • We never skip a valid pair because we exhaust all useful combinations.

Problem 2: Remove Duplicates from a Sorted Array (In-Place)

Given: A sorted array with duplicates. Goal: Remove duplicates in-place and return the count of unique elements.

This uses the same-direction pattern.

Walkthrough

Remove duplicates from [1, 1, 2, 2, 2, 3, 4, 4].

slow marks the position for the next unique element. fast scans ahead.

Step fast arr[fast] arr[slow]? Action Array State
1 1 1 Same as slow (1) Skip [1, 1, 2, 2, 2, 3, 4, 4]
2 2 2 Different! slow++, copy [1, 2, 2, 2, 2, 3, 4, 4]
3 3 2 Same as slow (2) Skip  
4 4 2 Same Skip  
5 5 3 Different! slow++, copy [1, 2, 3, 2, 2, 3, 4, 4]
6 6 4 Different! slow++, copy [1, 2, 3, 4, 2, 3, 4, 4]
7 7 4 Same as slow (4) Skip  

Unique elements: 4 (indices 0–3 contain [1, 2, 3, 4]). ✅

Java Implementation

public class RemoveDuplicates {

    /**
     * Removes duplicates from a sorted array in-place.
     * Returns the count of unique elements.
     *
     * Uses same-direction two pointers:
     *   slow = boundary of the unique portion
     *   fast = scanner looking for new unique values
     */
    public static int removeDuplicates(int[] sortedArr) {
        if (sortedArr.length == 0) return 0;

        int slow = 0; // last index of the unique portion

        for (int fast = 1; fast < sortedArr.length; fast++) {
            if (sortedArr[fast] != sortedArr[slow]) {
                slow++;
                sortedArr[slow] = sortedArr[fast]; // place the new unique value
            }
            // if equal, just skip — fast moves forward automatically
        }

        return slow + 1; // count of unique elements
    }

    public static void main(String[] args) {
        int[] arr = {1, 1, 2, 2, 2, 3, 4, 4};
        int uniqueCount = removeDuplicates(arr);
        System.out.println("Unique count: " + uniqueCount); // Output: 4
        // arr[0..3] = [1, 2, 3, 4]
    }
}

Problem 3: Check If a String Is a Palindrome

Given: A string. Goal: Determine if it reads the same forwards and backwards.

This is another opposite-direction pattern.

Java Implementation

public class PalindromeCheck {

    /**
     * Checks if a string is a palindrome (ignoring case).
     * Uses opposite-direction two pointers.
     */
    public static boolean isPalindrome(String s) {
        int left = 0;
        int right = s.length() - 1;

        while (left < right) {
            if (Character.toLowerCase(s.charAt(left)) !=
                Character.toLowerCase(s.charAt(right))) {
                return false; // mismatch found
            }
            left++;
            right--;
        }

        return true; // all characters matched
    }

    public static void main(String[] args) {
        System.out.println(isPalindrome("RaceCar")); // true
        System.out.println(isPalindrome("Hello"));   // false
    }
}

Time & Space Complexity

Problem Time Space Why
Two Sum (sorted) $O(n)$ $O(1)$ Each pointer moves at most $n$ times total.
Remove Duplicates $O(n)$ $O(1)$ Single pass with fast.
Palindrome Check $O(n)$ $O(1)$ Pointers meet in the middle.

The beauty of Two Pointer is that all these problems would need $O(n^2)$ with brute-force nested loops, but with two pointers they drop to $O(n)$.


When to Use / When NOT to Use

✅ Use When ❌ Avoid When
Array is sorted (or can be sorted) Data is unsorted and sorting would change the answer (e.g., index-based problems)
Looking for pairs or sub-arrays that satisfy a condition The problem requires checking all possible subsets (not just pairs)
You want to optimise from $O(n^2)$ to $O(n)$ A hash-based approach would be simpler and sufficient

Practice Problems

  1. Two Sum II – LeetCode #167 — Opposite-direction pointers on a sorted array.
  2. Remove Duplicates from Sorted Array – LeetCode #26 — Same-direction pointers.
  3. Valid Palindrome – LeetCode #125 — Opposite-direction with character filtering.
  4. Container With Most Water – LeetCode #11 — A clever two-pointer greedy problem.
  5. 3Sum – LeetCode #15 — Combine sorting with two pointers inside a loop.

What’s Next?

The Two Pointer technique works with pairs and endpoints. But what about problems involving contiguous sub-arrays? That is where the Sliding Window Technique comes in — a powerful extension of the same-direction pattern.



programmingalgorithmstwo-pointer Share Tweet Msg