Inorder Successor in BST
Return the node with the smallest value greater than p.val, or null.
Intuition
Successor = ceiling of p.val, exclusive. Walk from the root: going left past a node means that node is a successor candidate (it's bigger); going right discards. No parent pointers needed.
The successor is the smallest value strictly greater than p — which is the ceil question in disguise. That's why no in-order traversal is needed: the BST ordering already tells you that going left tightens an upper bound. Recognising a problem as "nearest neighbour on one side" collapses it to a single O(h) walk.
Approach
Candidate on left turns
node.val > p.val → node might be the successor; remember it and go left for something tighter.
Discard on right turns
node.val ≤ p.val → successor must be right of here.
Classic alternative
If p has a right subtree, the successor is that subtree's leftmost node — the walk above covers both cases uniformly.
Solution & live demo
Common pitfalls
Doing a full in-order traversal and taking the next node
vals = inorder(root) i = vals.index(p.val) return vals[i + 1]
while node:
if node.val > p.val:
succ = node
node = node.left
else:
node = node.rightCorrect, but O(n) time and O(n) space to answer a question the tree's shape already encodes. The walk is O(h) and allocates nothing.
Only looking inside p's right subtree
node = p.right while node.left: node = node.left return node
node = root
while node:
if node.val > p.val:
succ = node; node = node.left
else:
node = node.rightThat handles only the case where p has a right child. When it doesn't, the successor is an ancestor — the last node you turned left at — and this version returns nothing or crashes. Walking from the root covers both cases with no branching.
Edge cases
No left turn ever recorded → None.
Strict > comparison skips equal values correctly.