Don't memorize the two-pointer trick — watch the gap close. On a sorted array, put one finger on the smallest value and one on the largest, and add them. Too big? Pull the right finger in. Too small? Push the left out. The two pointers march toward each other exactly once — turning an O(n²) double loop into a single O(n) pass.
left & right · sorted array · converge · O(n)
LEFT / RIGHT
Two indices, one at each end of a sorted array.
THE MOVE
Sum too big → right−−. Too small → left++. Order tells you which.
ONE PASS
Each pointer only moves inward, so together they cover the array once.
O(n)
Linear time, O(1) space — vs the O(n²) of checking every pair.
two-pointers.sim — find a pair summing to 10
Ready
A sorted array and a target of 10. Left starts at the smallest value, right at the largest. Press Step to add the two ends and move a pointer based on the sum.
target = 10
0
Steps
15
Brute-force pairs
Why one pass is enough
The brute force checks every pair — n(n−1)/2 of them — because it has no idea where the answer is. Two pointers exploits the sorted order to always know which way to move: the right pointer sits on the biggest remaining value, so if the sum is already too big, that value can't be in any answer with the current left — drop it. Symmetrically, a too-small sum means the smallest value is too small. Every step eliminates a value for good, so the search finishes in one sweep.
01
Start at both ends
Left at index 0 (smallest), right at the last index (largest) of the sorted array.
02
Compare the sum
Add A[left] + A[right]. Equal to the target? Found it. Otherwise, the order tells you what to do.
03
Move inward
Sum too big → right−− (shed the largest). Too small → left++ (shed the smallest). Repeat.
04
Stop when they meet
If the pointers cross without a match, no such pair exists. Total moves ≤ n — that's the O(n).
Time
O(n)
Space
O(1)
Brute force
O(n²)
Needs
sorted input
The opposite-ends form needs sorted input, but the two-pointer idea is broader. Same-direction pointers remove duplicates or run a sliding window; fast-and-slow pointers detect a cycle in a linked list or find its middle. Spotting when a problem lets you replace a nested loop with two coordinated indices is one of the most valuable interview instincts.
SOLVE IT YOURSELF
Solve it: the closing gap
This one is yours to write — in Python or TypeScript, running for real in your browser. Edit the stub below, hit Run (or ⌘/Ctrl + Enter), and watch the hidden tests. Stuck? the hints are below and Reveal solution is one click away.
YOUR TASK
Given a sorted array nums and a target, implement pair_sum(nums, target): return the two indices[i, j] (i < j) whose values add up to target, or [-1, -1] if none. Use two pointers closing in from both ends — O(n), no hash map.
HINTS — 4 IDEAS
The array is sorted, so start one pointer at each end: lo = 0, hi = len − 1.
Look at nums[lo] + nums[hi]. Too small? move lo right to grow it.
Too big? move hi left to shrink it. Equal to target? that is your pair.
If the pointers meet (lo ≥ hi) with no match, return [-1, -1].
CPython · WebAssembly✓ Solved
1
1
Check yourself
1 · On a sorted array, the sum of the two pointers is bigger than the target. What do you do?
The right pointer holds the largest remaining value; if the sum is too big, that value can't help, so pull the right pointer inward.
2 · Why is the converging two-pointer scan O(n)?
No index is ever revisited — the two pointers between them cover n positions total, giving linear time.
3 · What does the opposite-ends two-pointer method require?
It uses the ordering to decide which pointer to move, so the array must be sorted (other two-pointer patterns don't need sorting).
Questions
What if the array isn't sorted?
Either sort it first (O(n log n), then the scan is O(n)), or use a hash table: store each value as you go and check whether target − value was already seen — O(n) time and O(n) space, no sorting. That's the standard unsorted two-sum.
How does this extend to three-sum?
Fix one element, then run the two-pointer scan on the rest for the remaining target. Sorting first makes it O(n²) overall — far better than the O(n³) triple loop.
What is the fast-and-slow pointer variant?
Two pointers moving at different speeds through a linked list: the fast one moves two steps, the slow one. If they meet, there's a cycle; when the fast one reaches the end, the slow one is at the middle. Same idea, different geometry.
Two fingers beat a double loop.
Sorted array, one from each end, move inward on the comparison. O(n²) becomes O(n).