01
Opposite ends (Two Pointers Sub-pattern)
One pointer at each end, walking towards each other. Each step compares the two ends and moves the side that can't do better.
Signals in the problem statement
- ›
sorted array + "pair with sum…"
- ›
"palindrome", "reverse"
- ›
the two ends compete (largest square, tallest wall)
- ›
"move the shorter / smaller side"
What makes it different
You always know which side to move because of order or symmetry. Ask: why can the element I'm leaving behind never be part of the answer?
Questions
ordered from “learn the idea” to “recognise it without help”- 1Valid PalindromeWalkthroughEasyBasic Anchor·LeetCode #125
- 2Two Sum II – Input Array Is SortedWalkthroughMediumBasic Reinforcement·LeetCode #167
- 3Reverse Vowels of a StringWalkthroughEasySlight Variation·LeetCode #345
- 4Squares of a Sorted ArrayWalkthroughEasyMedium·LeetCode #977
- 5Container With Most WaterWalkthroughMediumPattern Transfer·LeetCode #11
- 6Boats to Save PeopleWalkthroughMediumInterview-Level·LeetCode #881
- 7Pair Sum in a Sorted and Rotated ArrayWalkthroughMediumInterview-Level·GeeksforGeeks
- 8Trapping Rain WaterWalkthroughHardTricky / Edge Case·LeetCode #42
Template
opposite-template.cpp
// Opposite ends on a sorted array: find a pair with the given sum.
// Each step throws away one element that can never be part of the answer.
pair<int, int> pairWithSum(vector<int>& a, int target) {
int left = 0, right = (int)a.size() - 1;
while (left < right) {
int sum = a[left] + a[right];
if (sum == target) return {left, right};
if (sum < target) left++; // need bigger: a[left] is too small for every partner
else right--; // need smaller: a[right] is too big for every partner
}
return {-1, -1};
}Remember this · Two Pointers
Trigger
Sorted array, pairs/triplets with a target, comparing from both ends, compacting an array in place.
Think
If I compare the elements at two positions, can I safely discard one side?
Key question
Which pointer moves, and why can the skipped elements never be the answer?