Definition
- Two-pointer technique – a
leftpointer starts at the smallest value and arightpointer at the largest in a sorted array. - Decision rule – if
a[left] + a[right] < target, incrementleft; if greater, decrementright; if equal, return the pair. - O(n) time, O(1) space – each pointer moves at most n steps total, and no extra data structure is needed.
- Sorted precondition – the array must be sorted for the pointer movement reasoning to be correct.
- Alternative – on unsorted data, use a
HashMapapproach at the cost of O(n) extra space.
Rajesh at the National Bank of India has a sorted list of past deposit amounts and wants to know which two deposits together equal a disputed figure. He puts one finger on the smallest deposit and one on the largest. If their total is too small he slides the low finger up; if too big he slides the high finger down. He finds the pair without writing a side list of everything he has seen.
Understanding the Concepts
What is the Two Sum on Sorted Array problem?
Given a sorted array of integers and a target sum, find two elements that add up to the target. Return their indices or the values themselves. The array is guaranteed to be sorted in non-decreasing order.
At the National Bank of India, the reconciliation team checks whether a disputed charge equals the sum of two legitimate debits.
How do the two pointers work?
Keep left at index 0 and right at the last index. The loop runs while left < right.
- Compute
sum = a[left] + a[right]. - If
sum == target, return the pair. - If
sum < target, the only way to increase the sum is to moveleftup to a larger value. - If
sum > target, the only way to decrease the sum is to moverightdown to a smaller value.
package com.bank.reconciliation;
import java.math.BigDecimal;
public class TwoSumSorted {
public static int[] twoSum(BigDecimal[] amounts, BigDecimal target) {
int left = 0, right = amounts.length - 1;
while (left < right) {
BigDecimal sum = amounts[left].add(amounts[right]);
int cmp = sum.compareTo(target);
if (cmp == 0) {
return new int[]{left, right};
} else if (cmp < 0) {
left++;
} else {
right--;
}
}
return new int[]{-1, -1}; // no pair found
}
public static void main(String[] args) {
BigDecimal[] deposits = {
new BigDecimal("100"), new BigDecimal("200"),
new BigDecimal("350"), new BigDecimal("500"),
new BigDecimal("700")
};
BigDecimal target = new BigDecimal("550");
int[] result = twoSum(deposits, target);
System.out.println("Pair at indices: " + result[0] + ", " + result[1]);
System.out.println("Values: " + deposits[result[0]] + " + " + deposits[result[1]]);
}
}
Pair at indices: 1, 2
Values: 200 + 350
Why does moving a single pointer never miss a valid pair?
Because the array is sorted, when sum < target, the value at left is too small even when paired with the largest remaining value at right. So left can never be part of the answer and is safely discarded. The symmetric argument holds when sum > target. This correctness reasoning is the key insight interviewers probe.
How is this different from the HashMap Two Sum?
| Aspect | Sorted Two Pointers | HashMap Two Sum |
|---|---|---|
| Precondition | Array must be sorted | Works on unsorted data |
| Time | O(n) | O(n) |
| Space | O(1) | O(n) for the map |
| Multiple pairs | Easily extended to find all pairs | Needs extra bookkeeping |
| Index preservation | Indices are in the sorted array | Original indices preserved |
// HashMap approach for unsorted data
Map<BigDecimal, Integer> seen = new HashMap<>();
for (int i = 0; i < amounts.length; i++) {
BigDecimal complement = target.subtract(amounts[i]);
if (seen.containsKey(complement)) {
return new int[]{seen.get(complement), i};
}
seen.put(amounts[i], i);
}
What about integer overflow?
For very large amounts, a[left] + a[right] can overflow int or long. In real financial code at the National Bank of India, Pankaj mandates BigDecimal for all money operations so sums are exact and overflow is not a concern.
What are the edge cases?
- No valid pair – pointers cross without finding a match; return a sentinel like
{-1, -1}. - Multiple valid pairs – the algorithm finds one; to find all, continue after recording the pair.
- Duplicate elements – works correctly because the pointers are distinct indices.
- Array of length less than 2 – no pair possible; return sentinel.
- Target equals double of a single element – two pointers can land on distinct indices with the same value.
What are common mistakes?
// Wrong: using the same index for both elements
if (amounts[left].add(amounts[left]).compareTo(target) == 0) { ... }
// This checks one element against itself, not two distinct elements
// Correct: always ensure left < right
while (left < right) {
BigDecimal sum = amounts[left].add(amounts[right]);
// ...
}
What should a senior engineer know?
The two-pointer technique generalizes to Three Sum (fix one element, two-pointer on the rest) and K Sum problems. The O(1) space advantage matters in memory-constrained environments like processing large batch files. When the data arrives unsorted and sorting would destroy original indices, the HashMap approach is the correct choice.
What are common interview follow-up questions?
- What if the array is unsorted? – Use a HashMap.
- Can you extend to Three Sum? – Yes, fix one element and two-pointer on the rest.
- What about returning all pairs? – After finding a pair, skip duplicates and continue.
- What if no pair exists? – Return a sentinel value.
Visual Overview
┌────────────────────────────────────────────────────────┐ │ Two Sum on Sorted Array: Two Pointer Walkthrough │ ├────────────────────────────────────────────────────────┤ │ │ │ Array: [100, 200, 350, 500, 700] Target: 550 │ │ L R │ │ │ │ Step 1: 100+700 = 800 > 550 → R-- │ │ L R │ │ │ │ Step 2: 100+500 = 600 > 550 → R-- │ │ L R │ │ │ │ Step 3: 100+350 = 450 < 550 → L++ │ │ L R │ │ │ │ Step 4: 200+350 = 550 == 550 → FOUND! [1, 2] │ │ │ └────────────────────────────────────────────────────────┘
Key Takeaway
Two Sum on a sorted array finds two values that add up to a target using opposite-end two pointers, giving O(n) time and O(1) extra space. Place a left pointer on the smallest value and a right pointer on the largest. If their sum is less than the target, move left up; if greater, move right down; if equal, return the pair.
The correctness argument is the part interviewers want to hear. Because the array is sorted, when the current sum is too small, the smallest value can never contribute to a valid pair even alongside the largest remaining value, so you can safely discard it by advancing the left pointer, and the mirror image holds when the sum is too large.
The trade-off against the HashMap version is memory. The HashMap approach works on unsorted data in linear time but needs O(n) extra space, while the sorted two-pointer approach needs no extra space but requires the input to already be sorted.
In a banking project at the National Bank of India, the reconciliation service uses this to check whether a disputed charge equals the sum of two legitimate debits, working in BigDecimal so there is never a rounding error.
Remember one sentence: On a sorted array, two opposite-end pointers find a target-sum pair in O(n) time and O(1) space by discarding the smaller value when the sum is too small and the larger when too large.
---