When to use two pointers or a sliding window
Use two pointers when you have:
- A sorted array and you want a pair or triple with a given sum, or to merge two sorted lists.
- A question that compares the two ends, such as a palindrome or the container with the most water.
- A need to change an array in place, for example removing duplicates or moving zeros to the end.
- A linked list where you want the middle, or to know whether it loops (fast and slow pointers).
Use a sliding window when you have:
- A question about a contiguous stretch of an array or string: the longest, the shortest, the biggest total, or "at most k different items".
- A running total or count over the last
kitems, such as a moving average or the busiest minute.
Use something else when:
- The array is not sorted and you want a pair: use a hash map.
- The items you want are not next to each other (a subsequence): use dynamic programming.
- The window total can go down when you add an item (negative numbers) and you need an exact sum: use prefix sums with a hash map.
There is no library to import. This is a technique, not a data structure. Languages give you helpers (see the real-world section), but the idea is two integers and a loop.
How two pointers and sliding windows work
A pointer here is just an index. Two pointers means keeping two indexes and moving them according to a rule, instead of using a nested loop that tries every pair.
The pointers only move forward (or inwards), never back, so each item is visited a constant number of times and the whole pass is O(n).
There are three common shapes:
- Inwards from both ends. Start one pointer at the left and one at the right of a sorted array. If the sum is too small, move the left pointer right. If it is too big, move the right pointer left. Each move rules out a whole group of pairs.
- Fast and slow. Both start at the same place and one moves faster, for example two steps for every one. In a linked list, when the fast pointer reaches the end, the slow one is at the middle. If the list loops, the fast pointer eventually catches the slow one.
- A window. The left and right pointers are the edges of a stretch of items. The right edge grows the window and the left edge shrinks it. A fixed window always holds
kitems. A variable window grows and shrinks to keep a rule true, such as "no repeated letters".
The trick that makes a window fast is to update, not recompute. When the window slides one step, add the item that came in, subtract the item that left, and the total is correct. You never add up all k items again.
Try it
Pick one of the three techniques, then press Run and step through. Watch the pointers and the counters.
Two pointers and sliding window
Step 1 of 6 · Press Space to play, arrow keys to stepFind two numbers that add up to 10. The array is sorted, so put one pointer at each end.
- pairs checked:
- 0
- brute force would check:
- 15
Things to try:
- Pair with a given sum: use
1 3 4 6 8 11with target10. It finds4 + 6after 5 checks, where checking every pair could take up to 15. Then use target2: it proves no pair exists after 5 checks, where checking every pair would take 15. - Best total of k in a row: use
2 1 5 1 3 2 9 1withk = 3. Each slide adds one number and removes one. The best total is 14, starting at index 4. - Longest run with no repeats: use
abcabcbb. The window grows toabc, then shrinks from the left whenever a letter repeats. The answer is length 3.
Two pointers and sliding window operations
Inwards pointers (sorted array). Compare the two items. Decide which pointer to move from how the sum compares with the target. Stop when they meet.
Fixed window. Add up the first k items once. Then for each step, add the new item on the right and subtract the old item on the left. Keep the best total seen.
Variable window. Move the right edge one item at a time. If the new item breaks the rule, move the left edge forward until the rule holds again. Record the window length after each step.
Fast and slow pointers. Move the slow pointer one step and the fast pointer two steps. If they ever point at the same item, there is a loop. If the fast pointer reaches the end, there is none.
Interview fact. A while loop inside a for loop does not mean O(n²). If the left pointer only ever moves forward, it moves at most n times across the whole run, so the total work is about 2n, which is O(n).
Two pointers and sliding window time complexity
| Technique | Time | Extra memory |
|---|---|---|
| Inwards pointers on sorted data | O(n) | O(1) |
| Fixed sliding window | O(n) | O(1) |
| Variable sliding window (numbers) | O(n) | O(1) |
| Variable window with a set of seen items | O(n) | O(k), where k is the number of distinct items |
| Fast and slow pointers on a linked list | O(n) | O(1) |
If the data is not sorted and you must sort it first for inwards pointers, add O(n log n) for the sort.
Two pointers vs other approaches
The right choice depends on the problem. n is the number of items.
| What you need | Two pointers or window | Nested loops | Hash map | Sort, then binary search |
|---|---|---|---|---|
| Pair with a given sum, array already sorted | O(n) time, O(1) memory | O(n²) | O(n) time, O(n) memory | O(n log n) |
| Pair with a given sum, array not sorted | O(n log n) (sort first) | O(n²) | O(n) time, O(n) memory | O(n log n) |
Best total of k in a row | O(n) | O(n × k) | Not useful | Not useful |
| Longest run with no repeats | O(n) | O(n²) or worse | O(n), also a window | Not useful |
| Extra memory for numbers | O(1) | O(1) | O(n) | O(1) |
| Needs sorted input | Only for the inwards version | No | No | Yes |
The bold cells show where each wins. Two pointers and windows are the cheapest on memory, but they need either sorted data or a question about a contiguous stretch.
How to explain two pointers and sliding windows in an interview
- Say what each pointer means: "left is the start of the window, right is the next item to add."
- Say why the pointers only move forward, and so why it is O(n) even with an inner loop.
- State what you update when it moves: "add the new item, subtract the old one", not "recompute the window".
- Say when it does not apply: unsorted pairs (use a hash map), non-contiguous choices (use dynamic programming).
- Give both costs: O(n) time, O(1) memory, or O(k) if you keep a set.