Two Pointers Technique

Two Pointers Technique

The two pointers technique is a common algorithmic pattern that uses two pointers to solve problems efficiently. It's particularly useful for array and string problems.

Types of Two Pointers

  • Opposite Directional: Pointers start from opposite ends and move toward each other
  • Same Directional: Pointers start from the same end and move in the same direction
  • Fast and Slow: One pointer moves faster than the other

Opposite Directional Example - Two Sum in Sorted Array

// Find two numbers that sum to target in sorted array
public int[] twoSum(int[] numbers, int target) {
    int left = 0;
    int right = numbers.length - 1;
    
    while (left < right) {
        int sum = numbers[left] + numbers[right];
        
        if (sum == target) {
            return new int[]{left + 1, right + 1}; // 1-indexed
        } else if (sum < target) {
            left++;
        } else {
            right--;
        }
    }
    
    return new int[]{-1, -1};
}

Same Directional Example - Remove Duplicates

// Remove duplicates from sorted array
public int removeDuplicates(int[] nums) {
    if (nums.length == 0) return 0;
    
    int writeIndex = 1;
    
    for (int readIndex = 1; readIndex < nums.length; readIndex++) {
        if (nums[readIndex] != nums[readIndex - 1]) {
            nums[writeIndex] = nums[readIndex];
            writeIndex++;
        }
    }
    
    return writeIndex;
}

// Remove duplicates allowing at most 2 occurrences
public int removeDuplicatesII(int[] nums) {
    if (nums.length <= 2) return nums.length;
    
    int writeIndex = 2;
    
    for (int readIndex = 2; readIndex < nums.length; readIndex++) {
        if (nums[readIndex] != nums[writeIndex - 2]) {
            nums[writeIndex] = nums[readIndex];
            writeIndex++;
        }
    }
    
    return writeIndex;
}

Fast and Slow Pointers - Cycle Detection

// Detect cycle in linked list (Floyd's Algorithm)
public boolean hasCycle(ListNode head) {
    if (head == null || head.next == null) return false;
    
    ListNode slow = head;
    ListNode fast = head;
    
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
        
        if (slow == fast) return true;
    }
    
    return false;
}

// Find middle of linked list
public ListNode findMiddle(ListNode head) {
    if (head == null) return null;
    
    ListNode slow = head;
    ListNode fast = head;
    
    while (fast.next != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    
    return slow;
}

Common Applications

  • Array Problems: Two sum, container with most water, 3 sum
  • String Problems: Palindrome check, reverse string
  • Linked List: Cycle detection, find middle, reverse
  • Optimization: Reduce time complexity from O(n²) to O(n)

Open full interactive app