Code Templates

This page provides reusable two pointers templates that you can adapt for various problems. Review the Concept Guide first for core understanding.

Opposite Direction Template

Use when working with sorted arrays to find pairs, check palindromes, or solve container problems.

function twoPointersOpposite(arr, target) {
    let left = 0;
    let right = arr.length - 1;

    while (left < right) {
        const sum = arr[left] + arr[right];

        if (sum === target) {
            return [left, right]; // Found
        } else if (sum < target) {
            left++;  // Need larger sum
        } else {
            right--; // Need smaller sum
        }
    }
    return [-1, -1]; // Not found
}
def two_pointers_opposite(arr: list, target: int) -> list:
    left, right = 0, len(arr) - 1

    while left < right:
        total = arr[left] + arr[right]

        if total == target:
            return [left, right]  # Found
        elif total < target:
            left += 1   # Need larger sum
        else:
            right -= 1  # Need smaller sum
    return [-1, -1]  # Not found
public int[] twoPointersOpposite(int[] arr, int target) {
    int left = 0, right = arr.length - 1;

    while (left < right) {
        int sum = arr[left] + arr[right];

        if (sum == target) {
            return new int[]{left, right}; // Found
        } else if (sum < target) {
            left++;  // Need larger sum
        } else {
            right--; // Need smaller sum
        }
    }
    return new int[]{-1, -1}; // Not found
}
vector<int> twoPointersOpposite(vector<int>& arr, int target) {
    int left = 0, right = arr.size() - 1;

    while (left < right) {
        int sum = arr[left] + arr[right];

        if (sum == target) {
            return {left, right}; // Found
        } else if (sum < target) {
            left++;  // Need larger sum
        } else {
            right--; // Need smaller sum
        }
    }
    return {-1, -1}; // Not found
}
func twoPointersOpposite(arr []int, target int) []int {
    left, right := 0, len(arr)-1

    for left < right {
        sum := arr[left] + arr[right]

        if sum == target {
            return []int{left, right} // Found
        } else if sum < target {
            left++  // Need larger sum
        } else {
            right-- // Need smaller sum
        }
    }
    return []int{-1, -1} // Not found
}
def two_pointers_opposite(arr, target)
  left, right = 0, arr.length - 1

  while left < right
    sum = arr[left] + arr[right]

    if sum == target
      return [left, right] # Found
    elsif sum < target
      left += 1  # Need larger sum
    else
      right -= 1 # Need smaller sum
    end
  end
  [-1, -1] # Not found
end

Same Direction Template

Use for removing duplicates, partitioning arrays, or in-place modifications.

function removeDuplicates(nums) {
    if (nums.length === 0) return 0;

    let slow = 0; // Position for next unique element

    for (let fast = 1; fast < nums.length; fast++) {
        if (nums[fast] !== nums[slow]) {
            slow++;
            nums[slow] = nums[fast];
        }
    }
    return slow + 1; // Length of unique portion
}
def remove_duplicates(nums: list) -> int:
    if not nums:
        return 0

    slow = 0  # Position for next unique element

    for fast in range(1, len(nums)):
        if nums[fast] != nums[slow]:
            slow += 1
            nums[slow] = nums[fast]
    return slow + 1  # Length of unique portion
public int removeDuplicates(int[] nums) {
    if (nums.length == 0) return 0;

    int slow = 0; // Position for next unique element

    for (int fast = 1; fast < nums.length; fast++) {
        if (nums[fast] != nums[slow]) {
            slow++;
            nums[slow] = nums[fast];
        }
    }
    return slow + 1; // Length of unique portion
}
int removeDuplicates(vector<int>& nums) {
    if (nums.empty()) return 0;

    int slow = 0; // Position for next unique element

    for (int fast = 1; fast < nums.size(); fast++) {
        if (nums[fast] != nums[slow]) {
            slow++;
            nums[slow] = nums[fast];
        }
    }
    return slow + 1; // Length of unique portion
}
func removeDuplicates(nums []int) int {
    if len(nums) == 0 { return 0 }

    slow := 0 // Position for next unique element

    for fast := 1; fast < len(nums); fast++ {
        if nums[fast] != nums[slow] {
            slow++
            nums[slow] = nums[fast]
        }
    }
    return slow + 1 // Length of unique portion
}
def remove_duplicates(nums)
  return 0 if nums.empty?

  slow = 0 # Position for next unique element

  (1...nums.length).each do |fast|
    if nums[fast] != nums[slow]
      slow += 1
      nums[slow] = nums[fast]
    end
  end
  slow + 1 # Length of unique portion
end

Code Breakdown

  flowchart TD
    subgraph Opposite["Opposite Direction"]
        O1[left = 0, right = n-1] --> O2{left < right?}
        O2 -->|Yes| O3[Compare elements]
        O3 --> O4{Condition met?}
        O4 -->|Yes| O5[Record result]
        O4 -->|No| O6[Move appropriate pointer]
        O5 --> O6
        O6 --> O2
        O2 -->|No| O7[Done]
    end

    subgraph Same["Same Direction"]
        S1[slow = 0, fast = 1] --> S2{fast < n?}
        S2 -->|Yes| S3{Different element?}
        S3 -->|Yes| S4[slow++, copy element]
        S3 -->|No| S5[Skip]
        S4 --> S6[fast++]
        S5 --> S6
        S6 --> S2
        S2 -->|No| S7[Return slow + 1]
    end

Key Variables

  • left/right: Pointers moving toward each other
  • slow/fast: Pointers moving in same direction at different speeds
  • result: Accumulator for found pairs or modified array length

Variations

Three Sum (Fixed + Two Pointers)

function threeSum(nums) {
    nums.sort((a, b) => a - b);
    const result = [];

    for (let i = 0; i < nums.length - 2; i++) {
        if (i > 0 && nums[i] === nums[i - 1]) continue;

        let left = i + 1, right = nums.length - 1;
        while (left < right) {
            const sum = nums[i] + nums[left] + nums[right];
            if (sum === 0) {
                result.push([nums[i], nums[left], nums[right]]);
                while (left < right && nums[left] === nums[left + 1]) left++;
                while (left < right && nums[right] === nums[right - 1]) right--;
                left++; right--;
            } else if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }
    }
    return result;
}
def three_sum(nums: list) -> list:
    nums.sort()
    result = []

    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i - 1]:
            continue

        left, right = i + 1, len(nums) - 1
        while left < right:
            total = nums[i] + nums[left] + nums[right]
            if total == 0:
                result.append([nums[i], nums[left], nums[right]])
                while left < right and nums[left] == nums[left + 1]: left += 1
                while left < right and nums[right] == nums[right - 1]: right -= 1
                left += 1; right -= 1
            elif total < 0:
                left += 1
            else:
                right -= 1
    return result
public List<List<Integer>> threeSum(int[] nums) {
    Arrays.sort(nums);
    List<List<Integer>> result = new ArrayList<>();

    for (int i = 0; i < nums.length - 2; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) continue;

        int left = i + 1, right = nums.length - 1;
        while (left < right) {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum == 0) {
                result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                while (left < right && nums[left] == nums[left + 1]) left++;
                while (left < right && nums[right] == nums[right - 1]) right--;
                left++; right--;
            } else if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }
    }
    return result;
}
vector<vector<int>> threeSum(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    vector<vector<int>> result;

    for (int i = 0; i < nums.size() - 2; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) continue;

        int left = i + 1, right = nums.size() - 1;
        while (left < right) {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum == 0) {
                result.push_back({nums[i], nums[left], nums[right]});
                while (left < right && nums[left] == nums[left + 1]) left++;
                while (left < right && nums[right] == nums[right - 1]) right--;
                left++; right--;
            } else if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }
    }
    return result;
}
func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    result := [][]int{}

    for i := 0; i < len(nums)-2; i++ {
        if i > 0 && nums[i] == nums[i-1] { continue }

        left, right := i+1, len(nums)-1
        for left < right {
            sum := nums[i] + nums[left] + nums[right]
            if sum == 0 {
                result = append(result, []int{nums[i], nums[left], nums[right]})
                for left < right && nums[left] == nums[left+1] { left++ }
                for left < right && nums[right] == nums[right-1] { right-- }
                left++; right--
            } else if sum < 0 {
                left++
            } else {
                right--
            }
        }
    }
    return result
}
def three_sum(nums)
  nums.sort!
  result = []

  (0...nums.length - 2).each do |i|
    next if i > 0 && nums[i] == nums[i - 1]

    left, right = i + 1, nums.length - 1
    while left < right
      sum = nums[i] + nums[left] + nums[right]
      if sum == 0
        result << [nums[i], nums[left], nums[right]]
        left += 1 while left < right && nums[left] == nums[left + 1]
        right -= 1 while left < right && nums[right] == nums[right - 1]
        left += 1; right -= 1
      elsif sum < 0
        left += 1
      else
        right -= 1
      end
    end
  end
  result
end

Practice

Ready to apply these templates? Head to the Practice Problems page.

Pro Tip: The key to mastering two pointers is recognizing which variation fits the problem. Sorted input usually means opposite direction; in-place modification usually means same direction.