Intuition
Walk the search path for x. Every node ≤ x is a floor candidate — remember the best and go right hoping for closer; every node > x is too big — go left. The walk ends with the tightest candidate.
The mirror of ceil: the largest value not exceeding x. Same record-then-narrow skeleton, with both comparisons flipped. Recognising that these two problems are one problem with a sign change is worth more than memorising either — the same idea gives you inorder-successor and predecessor for free.
Approach
Candidates only from ≤
node.val == x → exact floor, stop. node.val < x → candidate; a better one may lurk right.
Too big → left
node.val > x contributes nothing; the floor must be in the left subtree.
One descent
No backtracking — the last recorded candidate is the answer.
Solution & live demo
Common pitfalls
Copying the ceil solution without flipping both halves
if root.val < x:
ans = root.val
root = root.leftif root.val < x:
ans = root.val
root = root.rightTwo things flip between floor and ceil — which comparison stores a candidate, and which direction tightens it. Flipping only the comparison and keeping ceil's direction walks away from every better answer, so you return the first value below x rather than the largest.
Seeding the answer with a real value
ans = root.val
ans = -1
When every node exceeds x there is no floor, and the problem expects -1. Seeding from the root reports a value that is larger than x, which is not a floor at all.
Edge cases
No node qualifies; return −1 (or None).
Early exit with x itself.