Two pointers and sliding windows · Data Structures and Algorithms
How do you solve list problems in one pass?
Course contentsWhy you need it
A big share of interview problems are about lists (arrays): pairs that add up to a target, reversing, removing duplicates from a sorted list. Two patterns, two pointers and the sliding window, turn many O(n²) brute-force answers into O(n).
The intuition
Two pointers: put one index at each end of a sorted list. If the pair's sum is too small, move the left one right; too big, move the right one left. Each step throws away one candidate, so it takes n steps at most.
Sliding window: to look at every run of k neighbours, don't re-add all k numbers each time. Slide: add the number that enters, subtract the one that leaves.
Definition
Two pointers
Two indexes that move toward each other (or in the same direction) so each element is visited once.
Sliding window
A range [left, right) over the list that moves forward, updating a running total instead of recomputing it.
Examples
Pair with a target sum
Try it yourselfThe list is sorted, so we can squeeze from both ends.
def pair_sum(xs, target):
left, right = 0, len(xs) - 1
while left < right:
total = xs[left] + xs[right]
if total == target:
return (xs[left], xs[right])
if total < target:
left += 1
else:
right -= 1
return None
print(pair_sum([1, 3, 4, 6, 9, 11], 13))- L2Start at both ends: 1 and 11.
- L71 + 11 = 12 is too small: move left.
- L103 + 11 = 14 is too big: move right.
- L133 + 9 = 13.
(3, 9)
Best 3-day total
Try it yourselfSales per day; find the best run of 3 days. The window slides one day at a time.
sales = [4, 2, 7, 1, 8, 3, 5]
k = 3
window = sum(sales[:k])
best = window
for i in range(k, len(sales)):
window += sales[i] - sales[i - k]
best = max(best, window)
print(best)- L3First window: 4 + 2 + 7 = 13.
- L6Add the day that enters, subtract the day that leaves.
- L8Windows: 13, 10, 16, 12, 16. Best is 16.
16
Common mistakes
Two pointers on an unsorted list
The squeeze only works because the list is sorted. Unsorted? Sort first (O(n log n)) or use a set (next lesson).
Off-by-one
range(k, len(xs)) and xs[i - k] must line up. Trace the first two steps by hand.
Quick quiz
1. What does this print?
xs = [1, 2, 3, 4, 5]
left, right = 0, len(xs) - 1
while left < right:
xs[left], xs[right] = xs[right], xs[left]
left += 1
right -= 1
print(xs)Show the answer
Answer: A
Swap the ends and move inward: this reverses the list in place.
2. Sliding a window of k over n numbers, how many additions does the running-total method need?
Show the answer
Answer: A
k for the first window, then one add and one subtract per step: O(n).
Practice
3 exercises in three steps: predict what a program prints, change a program to meet a new requirement, then write one from scratch. Your code runs in the browser and is checked the moment you submit.
- PredictTrace the pointers
Type exactly what this program prints.
- ModifyRemove duplicates in one pass
dedupe(xs)gets a sorted list and returns it without repeats. The inner loop scans all ofoutfor every item (O(n²)). Since the list is sorted, a repeat can only equal the last item kept. Use that to make it O(n). - WriteBest window
Write
best_window(xs, k)that returns the largest sum of any k consecutive numbers in xs (assume len(xs) ≥ k ≥ 1). Use a sliding window: O(n).
Practise this lesson
Open the interactive lesson to edit and run these examples and solve the exercises with instant feedback. Free to start, no sign-up.
Interactive lessons open in order. If you have not done the earlier ones yet, you start at the course map.
Terms in this lesson
| Term | Chinese | Definition |
|---|---|---|
| Array | 数组 | Items stored in order and reached by index; Python's list. |
| Two pointers | 双指针 | Two indexes moving through a list so each item is visited once. |
| Sliding window | 滑动窗口 | A moving range with a running total. |