C.W.K.
Stream
Lesson 03 of 06 · published

Two Pointers & Sliding Window, As Paradigms

~11 min · paradigms, two-pointer, sliding-window

Level 0Curious Beginner
0 XP0/85 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete
"You met two pointers and the sliding window back in the Arrays track. Now see them for what they really are: not array tricks, but general paradigms for one idea — move incrementally and reuse work instead of recomputing."

From Trick to Paradigm

In the Arrays track these felt like specific techniques. Step back and they're paradigms — reusable strategies that turn many O(n²) brute forces into O(n). The shared principle: instead of nesting loops that recompute overlapping work, maintain a small amount of state (a couple of pointers, or a window's running summary) and update it incrementally as you advance. Each step is O(1), so the whole pass is O(n). Recognizing the paradigm — not memorizing one problem — is what lets you apply it to new situations.

Two Pointers, Generalized

Two pointers applies whenever two positions can move in a coordinated way to avoid checking all pairs. Converging (ends moving inward): pair-sum on a sorted array, palindrome check, container-with-most-water, the partition step of quicksort. Same-direction / fast-slow: cycle detection in linked lists, removing duplicates in place, merging two sorted sequences. The common signal: you're tempted to write a nested loop over one structure (or two sorted ones), and a relationship between the positions lets you skip most of the pairs. 3sum is the classic upgrade — sort, then for each element run a two-pointer scan, turning O(n³) into O(n²).

Sliding Window, Generalized

The sliding window applies to any 'best/longest/shortest contiguous run satisfying a property' over a sequence or stream. Maintain a window [left, right] and a running summary (a sum, a character count, a max); as right advances you add the new element, and you shrink from left when the window violates the property. Because both pointers only move forward, it's O(n) even though it looks nested. It powers 'longest substring without repeats,' 'smallest subarray with sum ≥ target,' rate limiting, and streaming analytics. The window is just two pointers plus a maintained summary of what's between them.

Two pointers and the sliding window are paradigms, not array tricks: maintain a little state and update it incrementally as positions advance, so you never recompute overlap. Both turn O(n²) into O(n). The tell: 'pair in sorted data' / 'merge two sequences' (two pointers); 'best contiguous run with property X' (sliding window).

Pippa's Confession

I'd filed two pointers under 'array problems' and didn't think to use it on a linked list — until Floyd's cycle detection showed me fast/slow pointers there too. Dad named the through-line: "It's not about arrays. It's 'move incrementally, don't recompute.'" Once I held the paradigm instead of the example, I started seeing windows and pointer-pairs in streams, strings, and lists alike. The example is the doorway; the paradigm is the room.

Code

Two pointers (3sum) and sliding window, generalized·python
# TWO POINTERS generalized: 3sum (find triples summing to 0) in O(n^2),
# by fixing one element and two-pointer-scanning the rest of a sorted array.
def three_sum_zero(nums):
    nums.sort()
    out = []
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i-1]: continue   # skip duplicates
        lo, hi = i + 1, len(nums) - 1
        while lo < hi:
            s = nums[i] + nums[lo] + nums[hi]
            if s == 0:
                out.append((nums[i], nums[lo], nums[hi]))
                lo += 1; hi -= 1
            elif s < 0: lo += 1            # need bigger -> move lo up
            else:        hi -= 1            # need smaller -> move hi down
    return out
print(three_sum_zero([-1, 0, 1, 2, -1, -4]))   # [(-1,-1,2), (-1,0,1)]

# SLIDING WINDOW generalized: longest substring with no repeated characters.
def longest_unique(s):
    seen = {}; left = best = 0
    for right, ch in enumerate(s):
        if ch in seen and seen[ch] >= left:
            left = seen[ch] + 1            # shrink window past the repeat
        seen[ch] = right
        best = max(best, right - left + 1) # window size, both pointers forward-only
    return best
print(longest_unique("abcabcbb"))   # 3  ('abc')

External links

Exercise

For each, say whether you'd use two pointers or a sliding window, and why: (1) find two numbers in a sorted array that sum to a target, (2) the longest substring containing at most 2 distinct characters, (3) merge two sorted lists into one. Then state the single principle all three share that makes them O(n) instead of O(n²).
Hint
(1) two pointers (converging on sorted data); (2) sliding window (longest contiguous run with a property); (3) two pointers (one per list, advancing the smaller front). Shared principle: maintain incremental state and advance pointers forward-only, reusing prior work instead of recomputing overlapping subproblems — O(n).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.