Given a sorted array and a target number, find two elements that add up to the target.
Take [1, 3, 5, 7, 9, 11] — which two add up to 10?
Most people start checking pairs. 1 + 3? No. 1 + 5? No. 1 + 7? No. Keep going until something clicks — or you run out of combinations. With six numbers that's 15 pairs. With a hundred numbers, it's nearly five thousand.
But the array is sorted — and that changes everything.
Think about what “sorted” actually means for your search. If you pick two numbers and their sum is too high, you know something for certain: every number to the right of the larger one is even bigger, so pairing the smaller number with any of them is guaranteed to overshoot. You've just eliminated dozens of pairs with a single comparison.
The reverse holds too. If the sum is too small, every number to the left of the smaller one is even tinier — no point checking those either.
Sum = 12 → too high → 5 pairs eliminated
10 of 15 pairs remaining
Sorted order gives you something powerful here — but what exactly? And how much does it actually help? That's what we need to find out. First, let's feel the pain of not using it.
Here are six sorted numbers and a target of 10. Your job: find the pair that sums to 10.
Go ahead — tap any two cells to check their sum. Watch the counter climb as you search.
Pay attention to how many pairs you need to check. There's no shortcut here — you're just guessing and checking, one pair at a time. Each wrong pair tells you almost nothing about where the right one might be.
This is what O(n^2) feels like from the inside. Every new element adds not one new pair to check, but n - 1 new pairs. The work doesn't grow — it explodes. Six elements gave you 15 pairs. Twenty elements would give you 190. A hundred would give you 4,950. And you'd still be tapping, one pair at a time, with no better strategy than “try the next one.”
There has to be a better way. What if, instead of checking pairs at random, you could start with just two markers and let the sorted order tell you which direction to search?
Same six numbers. Same target. But now you have two markers — L and R. Tap any cell to place them, and their sum updates live.
Here's the challenge: try starting L at the far left and R at the far right. Once they're placed, look at the sum. Is it too high? Too low? Which marker would you move to fix it?
Notice something interesting about placing pointers at the edges. When L points to the smallest value and R points to the largest, the sum gives you maximum information. If 1 + 11 = 12 is too high, you know for certain that 1 paired with anything bigger than 11 would also be too high — but wait, there's nothing bigger. So the only useful move is to shrink the right side.
This is the beginning of a strategy. Not random guessing, but informed elimination.
The sum of your two pointers is either too high or too low. One of them needs to move — but which one?
This is the critical question. On a sorted array, only one direction can bring the sum closer to the target. The other direction makes things worse. Pick a direction. If you're wrong, watch the sum drift further away — that's the proof.
This is the mechanism that makes the algorithm work. It's not a heuristic or a guess — it's a logical certainty. Sorted order means values only increase left-to-right. So if the sum is too big, the only way to make it smaller is to replace the rightmost value with something smaller (move R left). If the sum is too small, the only way to make it bigger is to replace the leftmost value with something bigger (move L right).
There's no ambiguity. No branching. No “it depends.” Every sum comparison produces exactly one correct action.
You've been making pointer decisions by intuition for the last few screens. Before we name the pattern, pause and ask yourself: why did moving the wrong pointer always make things worse? What property of the array guaranteed that only one direction could help? Hold your answer.
When their sum is too big, the only value you can shrink is the right one — by moving R leftward. Moving L rightward would make the sum bigger, which is the wrong direction.
When their sum is too small, same logic in reverse. L must move right.
This is worth sitting with for a moment. In brute force, each failed pair gives you almost no information — you just move to the next pair. But here, each comparison tells you something powerful: an entire direction is eliminated. You'll never need to check any pair involving the value you just moved away from (in combination with the pointer that stayed). That's why this converges so quickly.
Each step provably shrinks the search space. And because the space shrinks by at least one element per step, you're guaranteed to either find the pair or exhaust all possibilities in at most n - 1 steps. No wasted work. No backtracking. (This property — where each step provably eliminates at least one candidate — is called monotonic elimination in algorithm design.)
Start: L=0, R=5
Remaining: 6 of 6
Something about sorted order makes this work. But what exactly? And what would break if the array weren't sorted? Hold that thought. First, let's see if your intuition holds up when the algorithm runs for real.
You know the rule now. At each step, the sum tells you which pointer to move. Predict it before the step executes — then see if you're right.
This is a different array with a different target. The rule doesn't change. Sum too low means L moves right. Sum too high means R moves left. Sum equals target means you're done.
Each prediction you get right reinforces the same invariant: the answer, if it exists, is always between L and R. Every step either finds the answer or provably eliminates one position from consideration. That's what makes this algorithm correct — it can never accidentally skip past a valid pair.
Eight elements this time. The array is longer, but the logic is identical. Sum too low, move L. Sum too high, move R.
The only difference is that more elements means more steps — but still linear steps, not quadratic pairs. Predict each move.
Notice how even with more elements, the number of steps stays proportional to the array length. You'll never take more than n - 1 steps, because each step eliminates at least one index from the search range. Compare that to brute force, where 8 elements would mean up to 28 pair checks.
Not every target has a valid pair. What does the algorithm do when the answer doesn't exist?
This array has a target that's impossibly large — no two elements can possibly sum to it. Step through and watch what happens as L and R converge toward each other.
Sum is 1 + 9 = 10. Which pointer should move?
This is the algorithm's termination condition. When L meets or crosses R, every possible pair has been implicitly checked. The convergence is the proof of completeness — L has seen every value from the left, R has seen every value from the right, and every meaningful combination of (small value, large value) has been compared against the target.
In code, this becomes the loop condition: while (left < right). Strict inequality, not <=. When left === right, both pointers reference the same element, and you can't form a pair from a single element. The algorithm terminates, and you know with certainty: no valid pair exists.
What would happen if the array weren't sorted? Would the pointer strategy you just learned still work? Before reading on, picture the array [9, 1, 5, 3, 7, 11] with pointers at the edges. The sum 9 + 11 = 20 is too high — so you move R left. Does that guarantee a smaller value? Think about it.
Everything so far assumed the array was sorted. Take that away, and the entire logical foundation collapses. It's not that the algorithm gets slower on unsorted data — it produces wrong answers.
If the array is [9, 1, 5, 3, 7, 11], the sum 9 + 11 = 20 is too high. Moving R leftward gives you 9 + 7 = 16. But that skipped over 3, and 9 + 3 = 12 might have been the answer. On unsorted data, “move leftward” doesn't mean “get a smaller value” — it means “get an arbitrary value.” The directional certainty is gone.
The unsorted array is 9153711 and target is 12. Will two-pointer find a valid pair?
This is a crucial interview insight. Two pointers is not a general-purpose technique — it has a precondition. If someone gives you an unsorted array and asks for two numbers summing to a target, you have two choices: sort it first (and use two pointers), or use a hash map for O(n) lookup without sorting. The next screen explores that second path.
One last comparison before you write the code. Same array, same target. Brute force on the left, two pointers on the right. Both racing to the answer.
Before the race starts, you'll predict the gap. Then watch both algorithms run side-by-side, step by step. The visual disparity makes O(n) vs O(n^2) visceral in a way that Big-O notation alone never does.
Brute Force
—
steps
Two Pointers
—
steps
Brute force checks every pair in [1, 2, ..., 21]. Two pointers converge from both ends. How many steps will each need to find target 19?
The gap you see here is small because the array is small. But it grows quadratically. With 100 elements, brute force might need ~4,950 comparisons while two pointers needs at most 99. With 1,000 elements: ~500,000 vs 999. The ratio isn't fixed — it keeps getting worse for brute force as n grows. That's the real meaning of O(n^2) vs O(n): not a constant speed difference, but a divergence that accelerates with scale.
You've run the algorithm by hand. You've predicted every step. Now write it.
Four blanks map to four decisions: where the pointers start, when the loop runs, and which pointer moves for each comparison outcome. Every blank corresponds to something you already did in the previous screens. If you get one wrong, think back to the specific screen where you learned that rule.
Here's the classic Two Sum problem — unsorted array, find two numbers that add to target. The brute force is O(n^2). Your job: make three small edits and watch the complexity collapse to O(n).
This isn't about memorizing a solution. Each edit follows logically from the previous one. You'll identify the bottleneck, extract the redundancy, then replace the entire inner loop with a single lookup. Three edits. Three insights. One breakthrough.
Look at the nested loops. What's the time complexity?
For each array state below: look at where the pointers are, compute the sum, compare to the target, and decide what happens next.
These aren't trick questions — they test whether you've internalized the rule deeply enough to apply it without thinking. The third scenario includes a subtlety about the termination condition that catches people in interviews.
If you got all three right on the first try, you own this pattern. The converging two-pointer technique appears in dozens of LeetCode problems: Two Sum II, Container With Most Water, 3Sum, Trapping Rain Water, and more. The specific array changes, the target changes, sometimes you're maximizing instead of matching — but the core mechanism is always the same. Sorted order. Two pointers. One direction per comparison. Guaranteed convergence.