LESSON 26 · INTERMEDIATE4 min read

The Two Pointers Pattern: Opposing Ends & Slow/Fast Collisions

Master the two pointers technique. Contrast inward-converging pointers for sorted arrays (Two-Sum II, Container With Most Water) with fast/slow pointers for in-place array compaction.

OpenJDK 21+ (LTS)Free to readModule 7 of 15
YOUR NEXT SMALL WINS

By the end, you’ll be able to…

  • Recognize sorted array problems solvable in O(N) time using converging inward pointers.
  • Prove the greedy correctness of the 'Container With Most Water' algorithm.
  • Implement Slow/Fast pointer compaction for in-place array deduplication in O(1) space.

01The Mechanics of Inward-Converging Pointers

When an array is sorted, searching for element pairs (such as finding two numbers that sum up to target T) can be naively done using nested loops in O(N^2) time. The Two Pointers technique reduces this to linear O(N) time with O(1) space.

We initialize two pointers: left at index 0 (smallest element) and right at index N - 1 (largest element). At each step, we calculate sum = arr[left] + arr[right]. Because the array is sorted: if sum < T, incrementing left is guaranteed to increase the sum. If sum > T, decrementing right is guaranteed to decrease the sum. When sum == T, we have found our match. Each step eliminates an entire row or column of the search space.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

02Container With Most Water: Greedy Correctness

In the classic 'Container With Most Water' problem, given an array of heights, we find two vertical lines that together with the x-axis form a container holding the maximum water: area = (right - left) * min(height[left], height[right]).

Why is moving the pointer pointing to the shorter line always mathematically correct? The width (right - left) will strictly decrease on the next step. If we moved the taller line, the new area could never exceed the current area because the height is bounded by the shorter line! The only possibility of finding a larger area is moving the shorter pointer inward in search of a taller line.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

03Dry-Run Trace Table for Container With Most Water

Let us trace the algorithm on heights = [1, 8, 6, 2, 5, 4, 8, 3, 7]:

In just 8 iterations, the algorithm visits the optimal container bounded by index 1 and index 8 with area 49, achieving O(N) time with O(1) space.

notes.txtPlain text
+-----+-------+------+---------+----------+-------+--------+----------------+| Step| Left  | Right| h[left] | h[right] | Width | Area   | Action         |+-----+-------+------+---------+----------+-------+--------+----------------+|  1  |   0   |  8   |    1    |    7     |   8   | 1*8=8  | h[0]<h[8]->L++ ||  2  |   1   |  8   |    8    |    7     |   7   | 7*7=49 | h[8]<h[1]->R-- ||  3  |   1   |  7   |    8    |    3     |   6   | 3*6=18 | h[7]<h[1]->R-- ||  4  |   1   |  6   |    8    |    8     |   5   | 8*5=40 | h[6]<=h[1]->R--||  5  |   1   |  5   |    8    |    4     |   4   | 4*4=16 | h[5]<h[1]->R-- ||  6  |   1   |  4   |    8    |    5     |   3   | 5*3=15 | h[4]<h[1]->R-- ||  7  |   1   |  3   |    8    |    2     |   2   | 2*2=4  | h[3]<h[1]->R-- ||  8  |   1   |  2   |    8    |    6     |   1   | 6*1=6  | h[2]<h[1]->R-- |+-----+-------+------+---------+----------+-------+--------+----------------+Max Area Found: 49!

04Why This Matters in Production

The two pointers pattern is widely utilized in database query engines (like Merge Joins on sorted tables), network packet stream reordering, and memory-constrained audio signal compression.

By replacing O(N^2) nested loops with O(N) pointer sweeps, production systems process massive telemetry streams in real time with zero extra heap allocations, preventing GC latency spikes.

05Production Architecture & Engineering Trade-Offs

In large-scale enterprise codebases, rigorous domain modeling relies on enforcing structural invariants at the type level rather than relying on defensive runtime validation. Modern Java leverages sealed types and records to turn runtime type errors into compile-time exhaustiveness guarantees. When designing domain transfer objects or persistent entities, ensuring immutability protects against unintended side effects across concurrent worker threads.

Furthermore, avoiding deep inheritance hierarchies in favor of composition and interface contracts eliminates fragile base class anti-patterns. By encapsulating state mutations within well-defined service boundaries and exposing pure functional transformers, software architects build maintainable, audit-compliant systems that scale smoothly across distributed cloud infrastructure.

LET IT CLICK

The ideas worth keeping.

  • Inward-converging two pointers solve search problems on sorted arrays in O(N) time.
  • Always identify which pointer movement guarantees pruning impossible candidate branches.
  • Two pointers achieve optimal O(1) auxiliary space by operating directly on the array.
TURN UNDERSTANDING INTO SOMETHING YOU CAN DO

Make it yours.

Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.

01

Exercise 1: 3Sum to Zero

Outline how sorting an array in O(N log N) time allows finding all unique triplets that sum to 0 in O(N^2) time using two pointers.

your_turn_1.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
Sort array. Loop index i from 0 to N-3. Skip duplicates. For each i, run two pointers (left = i + 1, right = N - 1) searching for sum == -nums[i]. Skip duplicates on match.

Sorting brings identical numbers together, allowing two pointers to eliminate pairs and duplicate triplets in O(N^2) time.

02

Exercise 2: Trapping Rain Water with Two Pointers

Explain how two pointers (left, right) with leftMax and rightMax variables calculate trapped rainwater in O(N) time and O(1) space.

your_turn_2.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
While left < right, if leftMax < rightMax, water at left is leftMax - height[left], increment left. Otherwise, water at right is rightMax - height[right], decrement right.

Water trapped at any column depends strictly on the smaller of the two boundaries, enabling single-pass O(1) space computation.

A SMALL QUESTION. A USEFUL NEXT STEP.

What stayed with you?

Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.

A LITTLE ACTIVE RECALL0 / 3 answered
01What prerequisite condition must usually be satisfied to use inward-converging two pointers for target sum searching?
02In Container With Most Water, why do we always advance the pointer with the smaller height?
03What is the space complexity of the two-pointer technique on arrays?
⚡CODING CHALLENGE
🔒Required to Mark Lesson Complete

Exercise 1: 3Sum to Zero

Outline how sorting an array in O(N log N) time allows finding all unique triplets that sum to 0 in O(N^2) time using two pointers.

EXPECTED OUTPUT
Build successful. (Java 15)
[Process exited normally]
Main.javaJava
Ctrl + ↵
Execution Console
Click "Run & Verify" (or press Ctrl + Enter) to test your code against the challenge.

Keep exploring.

The official references behind this lesson, when you want a second angle or the full details.

One lesson closer.

Reading is a start. Trying it yourself makes the connection.

Solve the hands-on coding challenge in the knowledge section to verify your code and unlock lesson completion.