Stage 1: Foundations·Two Pointers & Sliding Window
Medium#1675 min readTwo PointersSorted ArrayLeetCode

Two Sum II - Sorted

Converging Two Pointers

Why does moving the left pointer increase the sum? Understand the proof.

Published Apr 15, 2026

Problem

You are given a 1-indexed array of integers numbers that is sorted in nondecreasing order, and an integer target.

Return the 1-indexed positions of the two numbers such that they add up to target.

The input has exactly one solution, and you may not use the same element twice.

Input
numbers = [2,7,11,15], target = 9
Output
[1,2]
Input
numbers = [2,3,4], target = 6
Output
[1,3]
Input
numbers = [-1,0], target = -1
Output
[1,2]

Intuition

The array is sorted, which changes everything.

If the current sum is too small, moving the left pointer right can only increase it. If the current sum is too large, moving the right pointer left can only decrease it. That monotonicity gives us a deterministic search path instead of trying every pair.

This is the cleanest possible two-pointer setup: one pointer starts at each end, and each comparison tells you exactly which direction to move.

Approach

Converging Two Pointers

TimeO(n)
SpaceO(1)
Recommended

Start with left at the first element and right at the last element.

  • If numbers[left] + numbers[right] is too small, move left right.
  • If it is too large, move right left.
  • If it matches target, return the 1-indexed positions.

Because the array is sorted, every pointer move eliminates an entire class of impossible pairs.

use std::cmp::Ordering;

impl Solution {
    pub fn two_sum(numbers: Vec<i32>, target: i32) -> Vec<i32> {
        let mut left = 0usize;
        let mut right = numbers.len() - 1;

        while left < right {
            let sum= numbers[left] + numbers[right];

            match sum.cmp(&target) {
                Ordering::Less=> left = 1,
                Ordering::Greater=> right -= 1,
                Ordering::Equal=> {
                    return vec![(left + 1) as i32, (right + 1) as i32];
                }
            }
        }

        unreachable!("the problem guarantees exactly one solution");
    }
}
Rust · runnable

The 1-indexed detail is easy to miss. The algorithm is unchanged, but the returned indices are offset by one.

Trace

For numbers = [2,7,11,15], target = 9:

leftrightsumaction
0317too large, move right left
0213too large, move right left
019match, return [1,2]

The search is linear because each pointer only moves inward.

Edge cases

  • Negative numbers work the same way; sorted order still gives monotonic movement.
  • Minimal array length is still valid because the problem guarantees one solution.
  • Duplicate values do not require special handling when the solution is unique.
💡
Tip

This is the prototype for sorted two-pointer search. The same "too small move left, too large move right" proof is what makes #15 3Sum work after sorting.

Takeaway

Sorted order turns pair search into geometry.

Once the data is monotone, a single comparison tells you which half of the search space can be discarded forever. That is why two pointers are such a strong fit for sorted arrays.

More in Two Pointers & Sliding Window