---
title: "Two pointers (opposite ends)"
url: https://algopath.pro/patterns/two-pointers-opposite
language: en
summary: "Two indices start at the ends of a sorted array and walk toward each other. Each step moves whichever side is holding the answer back."
updated: 2026-08-24
---

# Two pointers (opposite ends)

Two indices start at the ends of a sorted array and walk toward each other. Each step moves whichever side is holding the answer back.

## How does Two pointers (opposite ends) work?

One index sits on the first slot, the other on the last. Together they name a candidate answer.

Read the value at each end and combine them. That gives a sum, a width, or a pair to compare.

Compare the result against the target. The comparison tells you which end is the problem.

If the combination is too small, move the left index right. Sorted order guarantees the value can only rise.

If it is too large, move the right index left. That is the only move that can lower it.

The loop ends when the two indices meet. Every element was read at most once.

- `[2, 4, 5, 8, 11] lo=0 hi=4` The target is 12. The pointers start at the two ends.
- `2 + 11 = 13` The sum is one over the target. Only the right end can lower it.
- `[2, 4, 5, 8, 11] lo=0 hi=3` Now 2 plus 8 is 10, which falls short. Only the left end can raise it.
- `[2, 4, 5, 8, 11] lo=1 hi=3` Now 4 plus 8 is 12. The target is hit exactly.
- `answer = [1, 3]` Three comparisons over five elements. Nothing was read twice.

## When should you use Two pointers (opposite ends)?

- sorted array (or you are allowed to sort)
- find a pair/triple with a target sum
- squeeze from both ends (container, area)
- palindrome check

## What is Two pointers (opposite ends) confused with?

- **Sliding window (variable)** - A window keeps a live span and both ends move forward. These pointers start apart and close in.
- **Hash set / map** - Hashing finds a complement in unsorted data, at the cost of O(n) memory. Two pointers need order but no memory.
- **Two pointers (same direction)** - There both indices move forward, one reading and one writing. Here they approach from opposite ends.
- **Binary search (array)** - Binary search hunts one fixed target and halves the range. Here the pair being compared changes every step.

## What is the time and space complexity of Two pointers (opposite ends)?

n up to 1e6 on sorted input gives O(n) time. Each pointer moves at most n steps, and space is O(1).

## A worked example of Two pointers (opposite ends)

### Container with most water

Each number is the height of a vertical line on a chart. Pick the two lines that hold the most water.

The area is the shorter line multiplied by the distance between them.

Start with the widest possible pair, one line at each end.

Moving the taller line inward can never help, because the shorter one caps the area. So move the shorter line and keep the best area seen.

```javascript
function maxArea(height) {
    let lo = 0;
    let hi = height.length - 1;
    let best = 0;

    while (lo < hi) {
        const area = Math.min(height[lo], height[hi]) * (hi - lo);
        best = Math.max(best, area);

        // the shorter side caps the area, so it is the only one worth moving
        if (height[lo] < height[hi]) lo++;
        else hi--;
    }

    return best;
}
```

## Common mistakes with Two pointers (opposite ends)

- **Forgetting that the input must be sorted** The whole method rests on order. On unsorted data the comparison points the wrong way.
- **Writing lo <= hi** That lets one index pair with itself. A pair of distinct elements needs lo < hi.
- **Moving both ends in one step** A valid pair can then be skipped without ever being tested. Move exactly one end per step.
- **Reporting a triple twice** After a hit, skip the equal values on both sides. Otherwise duplicates come back as separate answers.

## Which interview problems use Two pointers (opposite ends)?

- **Two sum II (sorted input)** The plain form: move the end that fixes the sum.
- **Three sum** Fix one value, then run two pointers over the rest.
- **Container with most water** Move the shorter side, because it caps the area.
- **Valid palindrome** Compare the two ends, then step inward.
- **Trapping rain water** Move the side with the smaller wall and bank the water.
- **Sort colors** The two ends collect the zeroes and the twos.
- **Squares of a sorted array** The largest square always sits at one of the ends.

## JavaScript

```javascript
function twoPointers(arr, target) {
    let lo = 0;
    let hi = arr.length - 1;
    while (lo < hi) {
        const sum = arr[lo] + arr[hi];
        if (sum === target) return [lo, hi];
        if (sum < target) lo++;
        else hi--;
    }
    return null;
}
```

## Python

```python
def two_pointers(arr, target):
    lo, hi = 0, len(arr) - 1
    while lo < hi:
        s = arr[lo] + arr[hi]
        if s == target:
            return (lo, hi)
        if s < target:
            lo += 1
        else:
            hi -= 1
    return None
```

## PHP

```php
function twoPointers(array $arr, int $target): ?array {
    $lo = 0;
    $hi = count($arr) - 1;
    while ($lo < $hi) {
        $sum = $arr[$lo] + $arr[$hi];
        if ($sum === $target) return [$lo, $hi];
        if ($sum < $target) $lo++;
        else $hi--;
    }
    return null;
}
```
