Last updated: Oct 27, 2026
Two Pointers vs Sliding Window
Two pointers and sliding window both use two indices to walk through an array or string in a single pass. Two pointers narrows down the search space to skip unnecessary comparisons. Sliding window keeps track of a contiguous range of elements and its state.
Two Pointers
Two pointers walk through an array or string to avoid extra comparisons and repeated passes. The pointers either move toward each other from opposite ends or move in the same direction.
When to Use (tips)
- The array is sorted.
- The task is to find a pair of elements with a certain property.
- Elements from opposite ends need to be compared.
- A property of the data allows ruling out whole groups of candidates at once.
Example: Count Number Pairs
Given a sorted array prices and a number budget, count the index pairs i < j where prices[i] + prices[j] <= budget.
function countPairs(prices: number[], budget: number): number {
let left = 0;
let right = prices.length - 1;
let pairs = 0;
while (left < right) {
if (prices[left] + prices[right] <= budget) {
pairs += right - left;
left++;
} else {
right--;
}
}
return pairs;
}
console.log(countPairs([1, 2, 3, 4, 5], 6));
// 6
Why It Works
- If the sum fits the budget, the current left element also fits with every element between
left + 1andright, because those are all smaller than or equal toprices[right]. That givesright - leftpairs at once, andleftmoves forward. - If the sum is over the budget, it has to get smaller. Since the array is sorted, moving
rightone step left is the only way to lower the sum.
Each step moves one pointer, so the loop runs at most n times.
Sliding Window
A sliding window is a contiguous range of elements between two indices. The window grows or shrinks as the task conditions change. Both pointers usually move from left to right and never move back.
When to Use
- The task is to find a substring or subarray.
- The answer is the longest or shortest contiguous range that meets a condition.
- A condition must hold inside the current range, for example no repeating characters.
Example: Longest Substring Without Repeating Characters
For the string "abcabcbb", find the length of the longest substring with no repeating characters.
leftis the start of the current window.rightis the end of the current window.lastSeenmaps each character to the index where it last appeared.maxLengthis the longest valid window found so far.
function lengthOfLongestSubstring(s: string): number {
const lastSeen = new Map<string, number>();
let left = 0;
let maxLength = 0;
for (let right = 0; right < s.length; right++) {
const char = s[right]!;
const prev = lastSeen.get(char);
if (prev !== undefined && prev >= left) {
left = prev + 1;
}
lastSeen.set(char, right);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
console.log(lengthOfLongestSubstring("abcabcbb"));
// 3 ("abc")
When a repeated character appears inside the window, left jumps to the position right after its previous occurrence, which removes the repeat. The prev >= left check keeps left from moving backward when the earlier occurrence is already outside the window. After that, the window length right - left + 1 updates maxLength.
Complexity
| Technique | Time | Space |
|---|---|---|
| Two pointers (count pairs) | O(n) | O(1) |
| Sliding window (longest substring) | O(n) | O(k), where k is the number of distinct characters |
Key Differences
| Two Pointers | Sliding Window | |
|---|---|---|
| Core idea | Two pointers cut down the search space | Two pointers mark the edges of a contiguous range |
| Typical task | Find a pair in a sorted array | Find a substring or subarray |
| Pointer movement | Toward each other or in the same direction | Usually both left to right |
| Tracked state | Depends on the task | State of the current window |
A sliding window is built on two pointers, but not every two-pointer task is a sliding window.