DEV Community

Timevolt
Timevolt

Posted on

Two Pointers: The Matrix of Array Traversal

The Quest Begins (The "Why")

I still remember the first time I faced a “find a pair that sums to X” question in an interview. My brain went straight to the obvious: loop over every element, then loop again to check every possible partner. O(n²) felt like swinging a blunt sword at a dragon—sure, you’d eventually hit something, but you’d be exhausted long before the beast fell. The interviewer’s polite nod and the ticking clock made it clear: there had to be a smarter way.

That moment sparked a tiny obsession. I started noticing how many array problems seemed to scream for a linear solution, yet the brute‑force approach kept creeping back into my notes. I wanted a technique that felt less like grinding and more like gliding—something that could cut the search space in half with each step. Enter the two‑pointer pattern.

The Revelation (The Insight)

At its heart, the two‑pointer trick is about information you already have. When the array is sorted (or can be sorted cheaply), you know the relative order of every element. If you pick the smallest and the largest values and add them, three things can happen:

  1. The sum is exactly the target – you’ve found your pair.
  2. The sum is too small – because the array is sorted, moving the left pointer right will only increase the sum (you’re swapping a small number for a slightly larger one).
  3. The sum is too large – moving the right pointer left will only decrease the sum (you’re swapping a large number for a slightly smaller one).

No need to revisit pairs you’ve already examined; each move discards an entire swath of impossible combinations. It’s like playing a game of “hot‑cold” where the temperature tells you precisely which direction to walk.

Why does this guarantee O(n)? Each pointer moves at most n steps total—never backward—so the total work is a linear scan. The sorted order gives us the monotonic guarantee that makes the greedy move safe.

Wielding the Power (Code & Examples)

Let’s see the technique in action with two classic interview problems.

Problem 1: Two Sum II – Input array is sorted

Statement: Given a sorted array numbers and a target target, return indices of the two numbers such that they add up to target. You may assume each input has exactly one solution, and you may not use the same element twice.

The naïve attempt (O(n²)):

def two_sum_bruteforce(numbers, target):
    n = len(numbers)
    for i in range(n):
        for j in range(i + 1, n):
            if numbers[i] + numbers[j] == target:
                return [i + 1, j + 1]   # 1‑based indices per LeetCode
    return []
Enter fullscreen mode Exit fullscreen mode

The two‑pointer victory (O(n)):

def two_sum_sorted(numbers, target):
    left, right = 0, len(numbers) - 1
    while left < right:
        cur = numbers[left] + numbers[right]
        if cur == target:
            return [left + 1, right + 1]      # 1‑based
        elif cur < target:   # need a bigger sum → move left forward
            left += 1
        else:                # cur > target → need a smaller sum
            right -= 1
    return []   # never happens given the problem guarantees a solution
Enter fullscreen mode Exit fullscreen mode

Why it works: The sorted order guarantees that moving left upward can only increase the sum, while moving right downward can only decrease it. We never skip a potential answer because any pair we discard is provably unable to hit the target.

Common trap: Forgetting that the input must be sorted. If you feed an unsorted array, the monotonic property vanishes and the algorithm can miss the solution. Either sort first (O(n log n)) or confirm the precondition.

Problem 2: Container With Most Water

Statement: Given n non‑negative integers height where each represents a vertical line at index i, find two lines that together with the x‑axis form a container holding the most water. Return that maximum area.

Brute force (O(n²)): check every pair, compute min(height[i], height[j]) * (j - i).

Two‑pointer solution (O(n)):

def max_area(height):
    left, right = 0, len(height) - 1
    best = 0
    while left < right:
        # area is limited by the shorter line
        h = min(height[left], height[right])
        width = right - left
        best = max(best, h * width)

        # move the pointer at the shorter line hoping for a taller one
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
    return best
Enter fullscreen mode Exit fullscreen mode

Why it works: The area is bounded by the shorter line. If we keep the shorter line and move the taller one inward, the width shrinks and the height cannot increase (we’re still limited by the same short line), so the area can only get worse. By discarding the taller line we never lose a better answer because any container using that taller line and a line farther inward would be no better than the one we just evaluated.

Common trap: Moving both pointers simultaneously or moving the taller pointer. Remember: you only advance the pointer at the shorter side; otherwise you might skip the optimal pair.

Why This New Power Matters

Mastering the two‑pointer pattern does more than shave a few milliseconds off your runtime—it rewires how you think about ordered data. Suddenly, problems that looked like nested loops reveal a graceful, linear dance. You start spotting the pattern everywhere: merging sorted lists, validating palindromes, finding subarrays with a given sum, even simulating the fast‑slow pointer cycle detection in linked lists.

In an interview, throwing out an O(n²) solution and replacing it with a clean O(n) two‑pointer approach signals that you can see structure beneath the surface. It’s the difference between brute‑forcing a puzzle and recognizing the hidden symmetry that lets you solve it in a glance.

And the best part? It’s surprisingly simple to implement. Once you internalize the monotonic guarantee—“moving this pointer can only make the sum/area go in one direction”—the code practically writes itself.

Your Turn

Grab a sorted array problem you’ve struggled with before (maybe “Remove Duplicates from Sorted Array” or “Sort Colors”). Try to reframe it with two pointers. Write the brute force first, then the optimized version. Notice how the invariants guide each step.

What’s the first two‑pointer challenge you’ll conquer? Drop your solution or a question in the comments—I’d love to hear how your quest goes!


Happy coding, and may your pointers always point in the right direction.

Top comments (0)