The most straightforward approach is to compare every pair of nodes in the tree. For each node, we traverse the entire tree to find the minimum absolute difference between this node's value and any other node's value. While simple to understand, this approach doesn't leverage the BST property and results in redundant comparisons.
dfs(node) that returns the minimum difference involving any node in the subtree rooted at node.dfs1(root, node) that traverses the entire tree and computes the minimum difference between node and every other node.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDiffInBST(self, root: Optional[TreeNode]) -> int:
def dfs(node):
if not node:
return float("inf")
res = dfs1(root, node)
res = min(res, dfs(node.left))
res = min(res, dfs(node.right))
return res
def dfs1(root, node):
if not root:
return float("inf")
res = float("inf")
if root != node:
res = abs(root.val - node.val)
res = min(res, dfs1(root.left, node))
res = min(res, dfs1(root.right, node))
return res
return dfs(root)In a BST, an inorder traversal visits nodes in sorted order. The minimum difference between any two nodes must occur between consecutive elements in this sorted sequence. So we perform an inorder traversal to collect all values into an array, then scan through the array to find the minimum difference between adjacent elements.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDiffInBST(self, root: Optional[TreeNode]) -> int:
arr = []
def dfs(node):
if not node:
return
dfs(node.left)
arr.append(node.val)
dfs(node.right)
dfs(root)
res = arr[1] - arr[0]
for i in range(2, len(arr)):
res = min(res, arr[i] - arr[i - 1])
return resInstead of storing all values in an array and then finding the minimum difference, we can compute the answer during the traversal itself. We keep track of the previously visited node during the inorder walk. At each step, we compare the current node's value with the previous node's value (since they are consecutive in sorted order) and update the minimum difference on the fly.
prev pointer to track the previously visited node during inorder traversal.res to infinity.prev exists, update res with min(res, current.val - prev.val).prev to the current node.res.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDiffInBST(self, root: Optional[TreeNode]) -> int:
prev, res = None, float("inf")
def dfs(node):
nonlocal prev, res
if not node:
return
dfs(node.left)
if prev:
res = min(res, node.val - prev.val)
prev = node
dfs(node.right)
dfs(root)
return resThe recursive inorder traversal can be converted to an iterative version using an explicit stack. This avoids recursion overhead and gives us more control over the traversal. The logic remains the same: we visit nodes in sorted order and compare each node with its predecessor.
cur to the root. Maintain prev to track the previous node.cur is not null:cur onto the stack.prev exists, update the minimum difference.prev to the current node and move cur to the right child.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDiffInBST(self, root: Optional[TreeNode]) -> int:
stack, prev, res = [], None, float("inf")
cur = root
while stack or cur:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop()
if prev:
res = min(res, cur.val - prev.val)
prev = cur
cur = cur.right
return resMorris traversal allows us to perform inorder traversal without using a stack or recursion, achieving O(1) extra space. The idea is to temporarily modify the tree by creating links from predecessor nodes back to their successors, allowing us to navigate the tree without additional memory. We traverse the tree, comparing consecutive values as before.
cur to the root and prevVal to track the value of the previous node visited.cur is not null:cur has no left child:cur (compare with prevVal and update minimum).prevVal and move to the right child.null, set it to cur and move left.cur, restore it to null, process cur, update prevVal, and move right.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDiffInBST(self, root: Optional[TreeNode]) -> int:
prevVal = res = float("inf")
cur = root
while cur:
if not cur.left:
if prevVal != float("inf"):
res = min(res, cur.val - prevVal)
prevVal = cur.val
cur = cur.right
else:
prev = cur.left
while prev.right and prev.right != cur:
prev = prev.right
if not prev.right:
prev.right = cur
cur = cur.left
else:
prev.right = None
if prevVal != float("inf"):
res = min(res, cur.val - prevVal)
prevVal = cur.val
cur = cur.right
return resThe most common mistake is treating this as a generic binary tree problem and comparing all pairs of nodes, resulting in O(n^2) time complexity. The BST property guarantees that inorder traversal produces a sorted sequence, so the minimum difference must occur between consecutive elements. Always use inorder traversal to reduce complexity to O(n).
In a sorted sequence, the minimum difference is always between adjacent elements. Some implementations incorrectly compare non-adjacent pairs or track global minimum/maximum values instead of the previous node, missing the optimal answer or overcomplicating the solution.