Linear DSA Patterns: Two Pointers, Windows, and Fast-Slow

Learn the common tricky patterns that appear again and again in array and linked-list problems.

Back to Learn DSA

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:

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:

Pattern 3: Monotonic stack

Use a monotonic stack when you need the next greater or next smaller value.

Common signs:

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.

Interactive walkthrough

Two Pointers Pattern

Move two indexes inward while checking a sorted array.