AlgoMaster Logo

Minimum Absolute Difference in BST

easyFrequency7 min readUpdated June 23, 2026

Understanding the Problem

We need to find the smallest absolute difference between any two node values in a BST. Comparing every pair of nodes would be O(n^2), but the BST property removes most of that work.

In a BST, an inorder traversal visits nodes in ascending order. In a sorted sequence, the minimum absolute difference always occurs between two adjacent elements, so we only need to compare consecutive nodes in the inorder traversal. The reason is arithmetic: for any sorted triple a < b < c, the gap (c - a) equals (c - b) + (b - a), which is at least as large as either adjacent gap. Skipping over an element can never produce a smaller difference.

Key Constraints:

  • 2 <= number of nodes <= 10^4 → The tree always has at least 2 nodes, so a valid pair always exists. With up to 10,000 nodes, an O(n) traversal is fast.
  • 0 <= Node.val <= 10^5 → Values are non-negative and bounded by 10^5, so the largest possible difference is 10^5. This fits in a 32-bit int, and subtracting two values can never overflow.

Approach 1: Inorder Traversal with Array

Intuition

Collect all node values with an inorder traversal, then scan the resulting list comparing each element with its neighbor to find the minimum gap.

An inorder traversal (left, node, right) of a BST visits nodes in ascending order, so the collected list is already sorted without a separate sort step. Once the list is sorted, the minimum absolute difference is the smallest gap between consecutive elements.

Algorithm

  1. Perform an inorder traversal of the BST and collect all node values into a list.
  2. Iterate through the list from index 1 to the end.
  3. At each index, compute the difference between the current element and the previous one.
  4. Track the minimum difference seen so far.
  5. Return the minimum difference.

Example Walkthrough

root
1Start inorder traversal: go left from root (4)
421curr36
values
1Values array empty, starting traversal
1/6

Code

Storing every value is unnecessary since we only ever compare adjacent pairs. The next approach keeps a single reference to the previously visited node and computes differences during the traversal itself.

Approach 2: Inorder Traversal with Previous Pointer (Optimal)

Intuition

Instead of collecting all values and scanning afterward, compute each gap during the traversal. The inorder traversal already visits nodes in sorted order, so keeping a reference to the previously visited node lets us compare every consecutive pair as we reach it. Each new node yields one candidate difference (node.val - prev.val), and the running minimum tracks the smallest seen.

This produces the same answer as Approach 1 with the same set of comparisons, but without holding the full list of values in memory.

Algorithm

  1. Initialize prev to null and minDiff to infinity (or Integer.MAX_VALUE).
  2. Perform an inorder traversal of the BST.
  3. At each node, if prev is not null, compute node.val - prev.val and update minDiff if this is smaller.
  4. Set prev to the current node before moving on.
  5. After the traversal, return minDiff.

Example Walkthrough

1Start inorder: visit node 1, prev=null, skip comparison
421curr36
1/6

Code

The time is optimal, but the recursion stack still uses O(h) space. Morris traversal removes the stack entirely and brings the extra space down to O(1).

Approach 3: Morris Inorder Traversal (Space Optimal)

Intuition

Morris traversal performs an inorder traversal with no recursion stack and no explicit stack. It uses the null right pointers that already exist in the tree as temporary "threads" back to ancestor nodes, so it can return upward without storing anything.

The mechanism: before descending into a left subtree, find its rightmost node, which is the inorder predecessor of the current node. Point that node's null right pointer at the current node. After the left subtree is fully traversed, following this thread leads back to the current node, signaling that its left side is done and it can be processed. The thread is then removed.

Algorithm

  1. Initialize current to the root, prev to null, and minDiff to infinity.
  2. While current is not null:
    • If current has no left child, process current (compare with prev, update minDiff), set prev = current, then move to current.right.
    • If current has a left child, find the inorder predecessor (rightmost node in the left subtree).
      • If the predecessor's right child is null, set it to current (create thread), then move current to current.left.
      • If the predecessor's right child is already current (thread exists), remove the thread, process current, set prev = current, then move to current.right.
  3. Return minDiff.

Example Walkthrough

1current=4, has left. Find predecessor (3), create thread 3->4, go left
4curr213pred6
1/7

Code