Two Sum in a BST takes the classic Two Sum question and changes the input from a flat array to a binary search tree. The twist rewards anyone who remembers one fact about BSTs: an in-order traversal hands you the values already sorted.
Problem. Given the root of a binary search tree and an integer k, return True if there exist
two different nodes whose values add up to k, and False otherwise.
Example: the BST holds 1, 3, 5, 7, 10, 14 and k = 12 → True, because 5 + 7 = 12.
The slow way first
The brute-force idea: for every node, search the tree again for k - value. That is O(n) searches, each O(h) deep, and it has to be careful not to match a node with itself. It works but it is fiddly and wastes the structure we were handed.
The question to ask: what do I already know about a BST that an array does not give me for free? A BST in-order traversal produces a sorted sequence. Once the data is sorted, Two Sum becomes the easy two-pointer sweep — no hashing, no repeated searches.
The idea: flatten, then two-pointer
Do it in two clean phases. Phase one: walk the tree in-order and collect the values into a list arr. Because it is a BST, arr comes out sorted. Phase two: put one pointer lo at the front and one pointer hi at the back, and compare arr[lo] + arr[hi] to k. Too big means shrink the sum by moving hi left; too small means grow it by moving lo right; equal means we found the pair.
The key insight: a sorted list lets each comparison tell us which pointer to move, so the two pointers only ever march toward each other and the whole sweep is one pass.
Walk through it
Step through the animation. First the in-order walk lights up the nodes smallest-to-largest and drops each value into the sorted row underneath. Then lo starts at 1 and hi at 14. Their sum 15 is too big, so hi steps left; then 11 is too small, so lo steps right; and the pointers keep closing in until 5 + 7 = 12 hits the target.
Pseudocode
arr = []
in-order traverse the BST, appending each value to arr # arr is now sorted
lo, hi = 0, len(arr) - 1
while lo < hi:
s = arr[lo] + arr[hi]
if s > k: hi = hi - 1 # sum too big, shrink it
elif s < k: lo = lo + 1 # sum too small, grow it
else: return True # found a pair
return FalseThe Python solution
def find_target(root, k):
arr = []
inorder(root, arr) # fills arr in sorted order
lo, hi = 0, len(arr) - 1
while lo < hi:
s = arr[lo] + arr[hi]
if s > k:
hi -= 1
elif s < k:
lo += 1
else:
return True
return Falseinorder(root, arr)does the left-root-right walk, appending each node value; because of the BST ordering,arrlands sorted.loandhistart at the two ends of the sorted list.s = arr[lo] + arr[hi]is the current pair sum we are testing.- If
s > kthe pair is too big, so we movehidown to a smaller value. - If
s < kthe pair is too small, so we moveloup to a larger value. - If they are equal we return
Trueimmediately; if the pointers meet without a hit, no pair exists.
Complexity
| Case | Time | Notes |
|---|---|---|
| In-order traversal | O(n) (moderate) | visit every node once |
| Two-pointer sweep | O(n) (moderate) | pointers close in, one pass |
O(n) (moderate)The flatten-and-sweep approach is O(n) time and O(n) space (for the list). That space is the cost of turning the tree into something the two-pointer trick can sweep. A more advanced solution uses a hash set during traversal for the same time but still O(n) space; the sorted-list view is the clearest to reason about.
When this pattern shows up
Whenever the input is a BST and the question is about values in sorted order — a kth-smallest, a range sum, a closest value, or a pair like this — think in-order traversal first. It converts the tree problem into a sorted-array problem you already know how to solve.
The two pointers must stay distinct: the loop guard is lo < hi, never lo <= hi. Allowing them to
land on the same index would let a node pair with itself, which the problem forbids.
Practice
After flattening to [1, 3, 5, 7, 10, 14] with k = 12, lo points at 1 and hi at 14 giving sum 15. Which pointer moves, and why?
1. Why does an in-order traversal of a BST give a sorted list?
2. On a sorted list, if arr[lo] + arr[hi] is greater than the target, which pointer moves?
3. Why must the loop condition be lo < hi rather than lo <= hi?
4. What is the space complexity of the flatten-then-sweep solution?