dsa4 min read

Two Pointers Technique from Scratch (2026)

Two Pointers Technique from Scratch (2026)

Published:  |  Category: Dsa  |  Reading time: ~15 min
Two Pointers Technique from Scratch (2026)

The two pointers technique is an efficient algorithmic pattern that uses two indices to traverse a data structure (usually an array) simultaneously. By moving the pointers intelligently based on certain conditions, we can solve many problems in O(n) time that would otherwise require O(n^2) brute force. The technique is especially powerful for problems involving sorted arrays, pair sums, and subarray optimization.

In this tutorial, we will implement the two sum (pair sum) problem, three sum problem, and container with most water problem. We will learn when to use two pointers, how to choose pointer movement strategies, and how to adapt the technique for different problem types.

Pair Sum - Two Sum Sorted

The two sum problem on a sorted array: find two numbers that add up to a target. The brute force approach checks all pairs in O(n^2). With two pointers, we place one at the start and one at the end. If the sum is too small, we move the left pointer right (to increase the sum). If too large, we move the right pointer left (to decrease it). This gives O(n) time and O(1) space.

This technique works because the array is sorted: moving pointers in the correct direction guarantees we make progress and don't miss any valid pairs. For unsorted arrays, we sort first or use a hash map.

def two_sum_sorted(arr, target):
    left, right = 0, len(arr) - 1
    while left < right:
        current_sum = arr[left] + arr[right]
        if current_sum == target:
            return (left, right)
        elif current_sum < target:
            left += 1
        else:
            right -= 1
    return None

def two_sum_hash(arr, target):
    seen = {}
    for i, num in enumerate(arr):
        complement = target - num
        if complement in seen:
            return (seen[complement], i)
        seen[num] = i
    return None

arr = [2, 7, 11, 15, 20]
print(two_sum_sorted(arr, 9))   # (0, 1)
print(two_sum_hash(arr, 9))    # (0, 1)

Three Sum Problem

The three sum problem finds all unique triplets that sum to zero. The brute force is O(n^3). With two pointers, we sort the array, fix one element, and use two pointers on the remaining subarray to find pairs that sum to the negative of the fixed element. This reduces the complexity to O(n^2).

We skip duplicate elements to avoid duplicate triplets. For each fixed element arr[i], we set left = i+1 and right = n-1, then apply the two-pointer technique. If the sum is zero, we add the triplet and move both pointers while skipping duplicates.

def three_sum(arr):
    arr.sort()
    result = []
    for i in range(len(arr) - 2):
        if i > 0 and arr[i] == arr[i-1]:
            continue
        left, right = i + 1, len(arr) - 1
        while left < right:
            total = arr[i] + arr[left] + arr[right]
            if total == 0:
                result.append([arr[i], arr[left], arr[right]])
                while left < right and arr[left] == arr[left+1]:
                    left += 1
                while left < right and arr[right] == arr[right-1]:
                    right -= 1
                left += 1
                right -= 1
            elif total < 0:
                left += 1
            else:
                right -= 1
    return result

arr = [-1, 0, 1, 2, -1, -4]
print(three_sum(arr))  # [[-1,-1,2],[-1,0,1]]

Container With Most Water

Given n non-negative integers representing heights, find two lines that together with the x-axis form a container that holds the most water. The area is min(height[left], height[right]) * (right - left). The brute force checks all pairs in O(n^2). With two pointers, we start with the widest container and move the shorter pointer inward, achieving O(n) time.

The key insight is that moving the taller pointer can never increase the area (the width decreases but the height is limited by the shorter pointer). So we always move the shorter pointer, potentially finding a taller line that increases the area.

#include 
#include 
#include 
using namespace std;

int maxArea(vector& height) {
    int left = 0, right = height.size() - 1;
    int max_area = 0;
    while (left < right) {
        int area = min(height[left], height[right]) * (right - left);
        max_area = max(max_area, area);
        if (height[left] < height[right])
            left++;
        else
            right--;
    }
    return max_area;
}

int main() {
    vector height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
    cout << "Max area: " << maxArea(height) << endl;  // 49
}

Two Pointers Variations and Patterns

Two pointers has many variations: same direction (slow/fast pointer for cycle detection, removing duplicates), opposite direction (two sum, container with most water), and sliding window (a special case where both pointers move in the same direction with a window between them). The choice depends on whether the array is sorted and the problem structure.

For linked lists, the fast and slow pointer (Floyd's cycle detection) detects cycles in O(n) time and O(1) space. For arrays, the technique is used in problems like removing duplicates in-place, partitioning arrays, and merging sorted arrays.

def remove_duplicates(arr):
    if not arr: return 0
    slow = 0
    for fast in range(1, len(arr)):
        if arr[fast] != arr[slow]:
            slow += 1
            arr[slow] = arr[fast]
    return slow + 1

def has_cycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast: return True
    return False

def max_subarray_sum_k(arr, k):
    window_sum = sum(arr[:k])
    max_sum = window_sum
    for i in range(k, len(arr)):
        window_sum += arr[i] - arr[i-k]
        max_sum = max(max_sum, window_sum)
    return max_sum

arr = [1,1,2,3,3,3,4]
print(remove_duplicates(arr))  # 4
arr2 = [2,1,5,1,3,4]
print(max_subarray_sum_k(arr2, 3))  # 9

Frequently Asked Questions

When to use two pointers?

Use two pointers when: (1) array is sorted or can be sorted, (2) looking for pairs/triplets with a condition, (3) need to find a subarray with certain properties, (4) cycle detection in linked lists.

Two pointers vs hash map?

Two pointers: O(n) time, O(1) space, requires sorted array. Hash map: O(n) time, O(n) space, works on unsorted arrays. Choose based on space constraints and whether sorting is allowed.

What is the sliding window technique?

Sliding window is a variation of two pointers where both pointers move in the same direction, maintaining a window. Used for subarray/substring problems: max sum subarray, longest substring without repetition, etc.

How does Floyd's cycle detection work?

Use two pointers: slow moves 1 step, fast moves 2 steps. If they meet, a cycle exists. To find the cycle start, reset one pointer to head and move both at same speed. They meet at the cycle start.

Originally published on Ayodhyyya. Last updated June 1, 2026.