---
title: Two Pointers vs Sliding Window
description: Two index-based techniques that replace nested loops with a single linear pass, differing in whether they track a pair of elements or a contiguous range.
tokens: ~1033
---

# 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`.

```typescript
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 + 1` and `right`, because those are all smaller than or equal to `prices[right]`. That gives `right - left` pairs at once, and `left` moves forward.
- If the sum is over the budget, it has to get smaller. Since the array is sorted, moving `right` one 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.

- `left` is the start of the current window.
- `right` is the end of the current window.
- `lastSeen` maps each character to the index where it last appeared.
- `maxLength` is the longest valid window found so far.

```typescript
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.