After arrays, stacks, queues, deques, and linked lists, the next jump is learning patterns.
Patterns help you recognize the shape of a problem before writing code.
Pattern 1: Two pointers
Use two pointers when a problem compares values from two positions.
Common signs:
- Sorted array
- Pair sum
- Palindrome check
- Reverse in place
- Remove duplicates
function hasPairWithSum(values, target) {
let left = 0;
let right = values.length - 1;
while (left < right) {
const sum = values[left] + values[right];
if (sum === target) return true;
if (sum < target) left++;
else right--;
}
return false;
}
Pattern 2: Sliding window
Use a sliding window when you need to inspect a continuous range.
Common signs:
- Subarray
- Substring
- Maximum or minimum window
- Fixed length
k - Longest range with a condition
Pattern 3: Monotonic stack
Use a monotonic stack when you need the next greater or next smaller value.
Common signs:
- Next greater element
- Daily temperatures
- Stock span
- Histogram rectangle
Pattern 4: Fast and slow pointers
Use fast and slow pointers when a linked list may have a cycle or when you need the middle node.
function middleNode(head) {
let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
Pattern 5: Prefix sum
Use prefix sums when repeated range-sum queries would otherwise be too slow.
prefix[i + 1] = prefix[i] + values[i];
rangeSum(left, right) = prefix[right + 1] - prefix[left];
Use the visualizer below to watch the two-pointer pair-sum pattern.
Practice links
Interactive walkthrough
Two Pointers Pattern
Move two indexes inward while checking a sorted array.