Many array and string problems ask about pairs or stretches of items. Checking every pair or every stretch is O(n²). Two pointers and sliding windows get the same answer in O(n) by moving two indexes through the data in a way that never has to go back.
Two pointers from both ends
Start one pointer at the beginning and one at the end, and move them towards each other. At each step, a simple rule decides which pointer moves.
Typical uses:
- Palindromes: compare
s[left]withs[right], then move both inwards. - Pairs in a sorted array: if
a[left] + a[right]is too small, moveleftup (to a bigger number); if it's too big, moverightdown. - Reversing in place: swap and move inwards.
Why it's correct for sorted pairs: when the sum is too small, a[left] can't be part of any answer with the remaining right-side numbers (they're all at most a[right]), so it's safe to discard it. Each step discards one item for good, so there are at most n steps.
1 + 11 = 12: too small, so move left up to a bigger number.
Spot it
Sorted input plus "find a pair" is a big hint. Reach for two pointers before you reach for a hash map.
Two pointers in the same direction
A "slow" and a "fast" pointer both move forward. The fast one explores; the slow one marks where to write or where the current stretch starts. Removing duplicates from a sorted array in place, or moving all zeros to the end, are classic examples.
Sliding window
A window is the stretch between left and right. Move right forward one step at a time to grow the window, and move left forward to shrink it whenever the window breaks a rule.
1left = 02for right, item in enumerate(items):right moves forward every step
3 add item to the window4 while the window breaks the rule:shrink only while the rule is broken
5 remove items[left] from the window6 left += 1left only ever moves forward too
7 the window [left, right] is now valid: update the answernow [left, right] is a valid window
Both pointers only move forward, so the total work is O(n), even with the while inside the for.
Grow until the total reaches 7: 2 + 3 + 1 + 2 = 8. Length 4.
| Window type | Shrink when... | Example |
|---|---|---|
| Longest valid window | the window becomes invalid | Longest stretch with no repeated letter |
| Shortest valid window | the window is valid (to see if a smaller one is) | Shortest stretch with sum ≥ target |
| Fixed size k | the window has more than k items | Best total of any 7 days in a row |
How to spot these problems
- "Contiguous", "substring", "subarray", "in a row" → think sliding window.
- "Sorted array" plus "pair" or "triplet" → think two pointers from both ends.
- "In place", "without extra space" → think slow and fast pointers.
Common mistakes
- Off-by-one window sizes: the window
[left, right]hasright - left + 1items. - Updating the answer at the wrong moment: for "longest", update after shrinking; for "shortest", update inside the shrinking loop.
- Forgetting to remove the outgoing item's count from the window's map when
leftmoves.
Nice work!
You've got the big idea. Try the quick quiz below, then put it to work on the practice problems.