DSA sheet · Binary Search Tree · search pattern

Closest Node in a BST

Given a BST and a number k, find how close the tree can get to k: the smallest absolute difference between k and any node's value. The teacher starts with the obvious plan (write the tree out in sorted order with inorder, then binary search the array), shows that the extra array is a waste, and then does the binary search directly on the tree, walking one path from the root with a simple while loop. That's O(h) time and O(1) space. It's the same "follow the signpost" move as Search in a BST, plus one variable that remembers the best difference so far.

Every part below follows the same order:
① the question in simple words → ② what the constraints tell us → ③ intuition → ④ building the conditions from examples → ⑤ approach steps → ⑥ code → ⑦ code line by line → ⑧ dry run → ⑨ complexity & remember

Part 0 · Before starting

What is a tree node?

A node holds a value and links to its left and right children (None if missing).

assumed node class (GFG calls the value data; we use val)
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

The BST rule

In a binary search tree, at every node: all values in the left subtree (the left child and everything below it) are smaller than the node, and all values in the right subtree are bigger. Short form: left subtree < node < right subtree. It has to hold for all nodes below, not just the direct children.

This is the tree the teacher uses (the lower part is drawn to match her inorder list):

          10
         /  \
        2    11
       / \
      1   5
         / \
        3   6
         \
          4

Check node 10: everything on the left (2, 1, 5, 3, 6, 4) is smaller, and 11 on the right is bigger. Check node 2: 1 is smaller, and 5, 3, 6, 4 are all bigger. Check node 5: 3 and 4 are smaller, 6 is bigger.

Why inorder of a BST gives a sorted list

Inorder traversal = visit the left subtree, then the node, then the right subtree. At every node, everything printed before it came from its left (smaller) and everything after it comes from its right (bigger). Since that's true at every level, the whole printout is in increasing order. For our tree: 1 2 3 4 5 6 10 11. We never sorted anything; the BST shape did it for us. Part A relies on this.

Absolute difference

The absolute difference between a and b is the distance between them on the number line, ignoring the sign: abs(a − b). abs(12 − 13) = 1 and abs(14 − 13) = 1. So a value below k and a value above k can be equally close.

Part A · Brute force: inorder into an array, then binary search

GFG · Find the closest element in BST (minDiff(root, K))

1The question in simple words

You get the root of a BST and an integer k. Over all nodes, find the smallest value of abs(node.val − k) and return that number (the difference, not the node).

The teacher's point: "closest" doesn't mean "just below" or "just above". For k = 13, both 12 and 14 would be distance 1. We want whichever number is nearest, on either side. That's why the problem is called "closest".

2What the constraints tell us

3Intuition

A sorted list makes "find the closest number" easy with binary search. And Part 0 told us inorder gives us a sorted list for free. So: flatten the tree with inorder, then binary search the list, remembering the smallest difference seen along the way.

4Building the logic from the example

Array [1, 2, 3, 4, 5, 6, 10, 11], k = 13. Look at the middle element:

Doubt: in the video the first middle element is 5, but my code picks 4. Who's right?
→ Both are fine. With 8 elements, the middle is between 4 and 5. With mid = (lo + hi) // 2 = (0 + 7) // 2 = 3, Python picks index 3, which is the value 4. The teacher just pointed at "the middle" to explain the idea. The steps below use the exact formula, and the answer is the same: 2.

5Approach steps

  1. Do an inorder traversal and put every value into a list (it comes out sorted).
  2. Binary search with lo = 0, hi = len − 1, and best = ∞.
  3. At each mid: update best with abs(arr[mid] − k). If equal → return 0. If smaller than k → lo = mid + 1, else hi = mid − 1.
  4. When lo passes hi → return best.

6Code (Python)

Closest node, brute force
class Solution:
    def minDiff(self, root, k):
        arr = []
        self.inorder(root, arr)            # sorted, because it's a BST

        best = float('inf')
        lo, hi = 0, len(arr) - 1
        while lo <= hi:
            mid = (lo + hi) // 2
            best = min(best, abs(arr[mid] - k))
            if arr[mid] == k:
                return 0
            if arr[mid] < k:
                lo = mid + 1                # need a bigger number
            else:
                hi = mid - 1                # need a smaller number
        return best

    def inorder(self, node, arr):
        if node is None:
            return
        self.inorder(node.left, arr)
        arr.append(node.val)
        self.inorder(node.right, arr)

7Code line by line

linewhat it means
self.inorder(root, arr)Left, node, right. Because of the BST rule, arr ends up sorted.
best = float('inf')Start with "infinitely far". Any real difference will be smaller and replace it.
mid = (lo + hi) // 2The middle of the part we haven't thrown away yet.
best = min(best, abs(arr[mid] - k))Remember this element's distance if it's the best so far.
if arr[mid] == k: return 0Exact match. Distance 0 is the smallest possible.
if arr[mid] < k: lo = mid + 1This value is too small. Anything left of it is smaller still, so drop the left half.
else: hi = mid - 1Too big. Drop the right half.
return bestThe search range is empty; the best distance we saved is the answer.

8Dry run (k = 13)

steplohimidarr[mid]abs(arr[mid] − 13)bestmove
10734994 < 13 → lo = 4
24756776 < 13 → lo = 6
3676103310 < 13 → lo = 7
4777112211 < 13 → lo = 8
end87lo > hi → return 2 ✓

9Complexity & remember

The teacher's question: did we really need to store every node? The tree is already "sorted" in its shape. We can run the same binary-search moves directly on the tree and skip the array.

RememberInorder of a BST is sorted. Sorted + "closest" → binary search, saving the best difference at each mid. Works, but costs O(n) time and O(n) extra space.

Part B · Optimal: walk down the tree, keep the best difference

Same question and constraints. The steps of the binary search stay; the array goes away.

1Intuition: the tree is a binary search already

Standing at a node, it plays the role of "mid". If the node is smaller than k, a closer number can only be bigger, so it can only be in the right subtree. Forget the whole left side. If the node is bigger than k, go left. Each step drops a whole subtree, and we visit only one node per level.

On the way down, keep one outside variable, ans, holding the smallest difference seen so far.

Doubt 1: when I go right from a node smaller than k, could the closest value be hiding on its left?
→ No. Everything in its left subtree is smaller than the node, and the node is already below k. So those values are even farther from k than the node, and we've already saved the node's own difference. Nothing we skip can beat what we keep.

2Why a while loop and not recursion?

A recursive walk would keep one call per level on the stack, which is O(h) space. We only ever move to one child and never need to come back, so a while loop that moves root down does the same job in O(1) space. The teacher deliberately chooses the iterative style to save that stack space.

3Building the conditions from examples

Example k = 13 → keep going right

At 10: 10 < 13. Save abs(10 − 13) = 3. A closer number must be bigger → go right. At 11: 11 < 13. Save 2 (better than 3). Go right → None. The loop ends, return 2.

Rule 1while root is not None: keep walking until we fall off the tree. Then the saved answer is final.
Rule 2node < k → root = root.right

Example k = 7 → left first, then right

At 10: 10 > 7, so a closer number must be smaller → go left.

Rule 3node > k → root = root.left

What if the node equals k? (k = 10, or k = 5)

Suppose k = 10. At the root the difference is already 0. Going left or right can't do better than 0, because a distance can't be negative. So we stop and return 0 immediately.

With k = 5: at 10 save 5, go left. At 2 save 3, go right. At 5 the difference is 0 → return 0. No need to look any further.

Rule 4node == k → return 0
Doubt 2: with three cases (equal, smaller, bigger), do I need three if-checks?
→ No. Once we've checked "equal" and "smaller", the only thing left is "bigger". So a plain else handles going left.

Where do we update the answer?

The teacher puts the update at the top of the loop, right after we know the node isn't None, and before any return or move. That way every node we stand on is counted before we leave it. Safer than trying to remember to update in each branch.

Doubt 3: why start ans at infinity?
→ We keep taking min(ans, new difference). The starting value must be bigger than any real difference, so the first node always replaces it. (Java uses Integer.MAX_VALUE; Python uses float('inf').)

4Approach steps

  1. ans = ∞.
  2. While root is not None:
  3. Update ans = min(ans, abs(root.val − k)).
  4. If root.val == k → return 0.
  5. If root.val < k → root = root.right. Else → root = root.left.
  6. After the loop → return ans.

5Code (Python)

Closest node, optimal
class Solution:
    def minDiff(self, root, k):
        ans = float('inf')
        while root is not None:
            ans = min(ans, abs(root.val - k))   # count this node first
            if root.val == k:
                return 0                        # can't beat 0
            if root.val < k:
                root = root.right               # need a bigger number
            else:
                root = root.left                # need a smaller number
        return ans

6Code line by line

linewhat it means
ans = float('inf')The best difference so far. Infinity, so the first real one replaces it.
while root is not None:Walk down until we fall off the tree.
ans = min(ans, abs(root.val - k))Count the current node's distance before deciding anything.
if root.val == k: return 0Exact match. No answer can be smaller than 0.
if root.val < k: root = root.rightThe node is too small. Its left side is even smaller, so skip it. Go right.
else: root = root.leftThe node is too big. Go left.
return ansNo exact match was found. Return the smallest distance we saw on the path.

7Dry run

Run 1: k = 7 (the teacher's main example)

steprootabs(root − 7)anscomparemove
1103310 > 7left → 2
2253 (5 is worse, no change)2 < 7right → 5
35225 < 7right → 6
46116 < 7right → None
endNoneloop ends → return 1 ✓ (6 is the closest)
          10          path taken for k = 7:
         /  \           10 → 2 → 5 → 6 → None
        2    11
       / \              skipped: 11, 1, and the 3-4 branch
      1   5
         / \
        3   6
         \
          4

Run 2: k = 6 → 10 (diff 4), go left. 2 (diff 4, no change), go right. 5 (diff 1), go right. 6: diff 0, and 6 == 6 → return 0 right away.

Run 3: k = 13 → 10 (3), right. 11 (2), right. None → return 2. Only 2 nodes visited.

(In the video the teacher once says "2 is greater, go right" for k = 5. She means 2 is smaller than 5, which is why we go right.)

8Complexity

9Remember

RememberWalk like Search in a BST. At each node: update ans first, equal → 0, smaller → right, bigger → left. Return ans at the end.

Part C · Revision page

Part A: inorder + binary searchPart B: walk the tree
usesinorder of a BST is sortedthe BST rule picks the side directly
nodes visitedall none per level
timeO(n)O(h): log n balanced, n skewed
extra spaceO(n) array + O(h) stackO(1)
at a nodeaction
always firstans = min(ans, abs(node − k))
node == kreturn 0
node < kgo right (need bigger)
node > kgo left (need smaller)
fell off the treereturn ans
If you remember only 5 lines 1. Closest = smallest abs(node − k); the winner can be below or above k.
2. Inorder of a BST is sorted, so binary search works, but the array costs O(n).
3. Do the binary search on the tree itself: smaller → right, bigger → left.
4. Update the answer at the top of the loop. Equal → return 0.
5. O(h) time (log n if balanced), O(1) space with a while loop.
Mistakes to avoid ✗ forgetting abs() (negative differences look "smaller")
✗ updating the answer after moving root (you skip a node, or read None)
✗ only looking for numbers below k (or only above)
✗ returning the node instead of the difference (read what the problem asks)
✗ starting ans at 0 instead of infinity
test it yourself (paste under either solution above)
root = TreeNode(10,
          TreeNode(2, TreeNode(1),
                      TreeNode(5, TreeNode(3, None, TreeNode(4)), TreeNode(6))),
          TreeNode(11))
s = Solution()
print(s.minDiff(root, 13))   # 2
print(s.minDiff(root, 7))    # 1
print(s.minDiff(root, 6))    # 0
print(s.minDiff(root, 5))    # 0
print(s.minDiff(root, -4))   # 5  (closest is 1)
print(s.minDiff(TreeNode(9), 4))  # 5

Based on this video: Closest Binary Search Tree Value