Hello and welcome back!
In our last lesson, we explored the Fast/Slow Pointer pattern, a clever technique for finding cycles in data structures. Today, we'll continue our deep dive into the Two Pointers theme by examining a different, yet equally fundamental, variation: using pointers that start at opposite ends of an array and move toward each other.
This "convergent" pattern is a cornerstone of array manipulation and is frequently tested in interviews. By the end of this lesson, you will be able to apply this pattern to solve classic LeetCode problems like 2Sum II, 3Sum, and Container with Most Water, moving you closer to your goal of mastering medium-level interview questions.
1. The Opposite-Ends Two-Pointer Pattern
In the previous lesson, both our pointers moved in the same direction but at different speeds. In this pattern, we initialize two pointers, one at the very beginning of an array (left) and one at the very end (right), and then systematically move them inward.

This approach is particularly powerful when dealing with sorted arrays, as the sorted nature of the data allows us to make intelligent decisions about which pointer to move, drastically improving efficiency over a brute-force approach.
Let's start with the canonical problem for this pattern.
2. The Foundation: Two Sum on a Sorted Array
The problem Two Sum II - Input Array Is Sorted (LeetCode 167) is a perfect introduction.
Problem: Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number.
A brute-force solution would use nested loops to check every pair of numbers, resulting in an O(n²) time complexity. We can do much better.
By placing one pointer at the start (left) and one at the end (right), we can check the sum of the elements at these pointers. Because the array is sorted, we can use the result of this sum to make a decisive move:
- If
current_sum < target, we need a larger sum. The only way to guarantee a larger sum is to move theleftpointer to the right. - If
current_sum > target, we need a smaller sum. The only way to guarantee a smaller sum is to move therightpointer to the left. - If
current_sum == target, we have found our pair.
This process continues until the pointers meet or cross, having checked all potential pairs in a single O(n) pass.
To see this in action, please study the following resource.
Two Pointers & Sliding Window - From Theory to LeetCode ...
The article 'Two Pointers & Sliding Window' provides a concise explanation and Python implementation for 'Two Sum II'. It perfectly illustrates the core logic of the opposite-ends pattern.
Please read the section titled '2. Two Sum II - Input Array Is Sorted (LeetCode 167)'. Focus on the logic for moving the left and right pointers based on the current_sum.
Test your understanding!
Given the sorted array numbers = [2, 7, 11, 15] and target = 9, trace the values of left, right, and current_sum until the solution is found.
- Initial state:
left = 0,right = 3 current_sum = numbers[0] + numbers[3] = 2 + 15 = 17- Since
17 > 9, what is the next move? And what are the new pointer positions?
Show answer
- Initial state:
left = 0,right = 3,current_sum = 17. - Since
current_sum > target, we need a smaller sum. We move the right pointer:rightbecomes2. - New state:
left = 0,right = 2. current_sum = numbers[0] + numbers[2] = 2 + 11 = 13.- Since
13 > 9, we again need a smaller sum. Move the right pointer:rightbecomes1. - New state:
left = 0,right = 1. current_sum = numbers[0] + numbers[1] = 2 + 7 = 9.current_sum == target. We found the solution at indices 0 and 1.
3. Scaling Up: The 3Sum Problem
Now let's tackle a more complex problem, 3Sum (LeetCode 15), which is a staple of FAANG interviews.
Problem: Given an integer array nums, return all the unique triplets [nums[i], nums[j], nums[k]] such that nums[i] + nums[j] + nums[k] == 0.
The key insight for 3Sum is to reduce it to the 2Sum II problem we just solved. Here's how:
- Sort the array: This is a mandatory first step. It costs O(n log n) but enables the efficient two-pointer approach and simplifies duplicate handling.
- Iterate through the array: Use a loop to fix one number, let's call it
a(fromnums[i]). - Solve
2Sum II: For the remainder of the array (from indexi+1to the end), find two numbers (bandc) that sum up to-a. This is exactly the2Sum IIproblem withtarget = -a.
The main challenge in 3Sum is handling duplicates to ensure the solution set is unique. Sorting is a huge help here. If we encounter the same number multiple times in our main loop, we can simply skip it to avoid generating duplicate triplets.
The following video provides an excellent, detailed walkthrough of the entire process, including the crucial logic for skipping duplicates.
The NeetCode video on '3Sum' breaks down this medium-level problem into manageable steps. It clearly explains the sorting strategy, the reduction to 2Sum, and the code-level details for handling duplicates.
Please watch the video from 01:52 to 06:52 to understand why sorting is essential and how the problem is reduced to 2Sum. Then, watch the code explanation from 07:44 to 11:54 to see how this logic is implemented, especially the parts that handle duplicate values.
Mastering the 3Sum pattern is a significant step. It combines sorting, the two-pointer technique, and careful duplicate handling—all essential skills for coding interviews.
4. A Different Logic: Container with Most Water
Let's look at one more problem that uses the opposite-ends pointer setup but applies a different logic for moving them: Container with Most Water (LeetCode 11).
Problem: You are given an integer array height of length n. Find two lines that, together with the x-axis, form a container that can hold the most water.
The area of water a container can hold is determined by its width and the height of its shorter side.Area = width * min(height[left], height[right])
We start with pointers at the widest possible configuration (left = 0, right = n-1). To find a potentially larger area, we must shrink the container by moving one of the pointers inward. Which one?
- If we move the pointer at the taller wall, our width decreases, and the new height will either be the same or smaller (it's still limited by the shorter wall). The area can only decrease.
- If we move the pointer at the shorter wall, our width decreases, but we have a chance of finding a new, much taller wall that could create a larger area, compensating for the reduced width.
This greedy choice—always moving the pointer of the shorter wall—is the key to solving this problem in O(n) time.
The following image provides a great visual breakdown of this logic.

For a code implementation that matches this logic, you can refer back to the dev.to article.
Two Pointers & Sliding Window - From Theory to LeetCode ...
Let's revisit the 'Two Pointers & Sliding Window' article, this time for its explanation of 'Container With Most Water'.
Please read section '3. Container With Most Water (LeetCode 11)'. Focus on the line if height[left] < height[right]:, as this is the implementation of the core greedy logic we just discussed.
Conclusion
In this lesson, we dissected the powerful "opposite-ends" two-pointer pattern. This is a must-know technique for your LeetCode toolkit.
Key Takeaways:
- The Opposite-Ends Two-Pointer pattern is ideal for problems involving pairs or triplets in sorted arrays.
- For sum-based problems (
2Sum II,3Sum), you move pointers based on whether thecurrent_sumis smaller or larger than thetarget. - For optimization problems (
Container with Most Water), you make a greedy choice at each step about which pointer to move to prune the search space effectively. - This pattern consistently reduces time complexity from O(n²) or O(n³) to O(n log n) (dominated by sorting) or O(n) (if the array is already sorted).
Preview of the Next Lesson:
We will continue building on the two-pointer theme by exploring how it can be used to partition arrays. We will specifically look at the famous Dutch National Flag problem, which uses a three-pointer variation to sort an array of three unique elements in a single pass. See you then