↓Skip to main content
  1. LeetCode/

LeetCode 99: Recover Binary Search Tree

·2 mins· ·
LeetCode Medium Tree Depth-First-Search Binary-Search-Tree Binary-Tree
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2026-10-25

  • Submissions: Accepted (first try)

Approach
#

The in-order traversal of a BST is strictly increasing (Tree Template 3). After two values are swapped, the in-order sequence contains inversions where the previous value is larger than the current one:

  • If the two nodes are not adjacent in in-order, there are two inversions. For 1 5 3 4 2 6 they are 5 > 3 and 4 > 2. The swapped nodes are the earlier node of the first inversion (5) and the later node of the last inversion (2).
  • If they are adjacent, there is one inversion, e.g. 1 3 2 4, and both nodes are in it.

So walk in-order and keep the previous node in prev:

  • On the first prev.val > node.val, set first = prev.
  • On every inversion, set second = node.

Then swap the values of first and second. Both cases give the right pair.

My Attempts
#

Accepted on the first try.

Solution
#

class Solution:
    def recoverTree(self, root: Optional[TreeNode]) -> None:
        self.first = None
        self.second = None
        self.prev = TreeNode(-inf)

        def inorder(node):
            if not node:
                return
            inorder(node.left)
            if self.prev.val > node.val:
                if not self.first:
                    self.first = self.prev
                self.second = node
            self.prev = node
            inorder(node.right)

        inorder(root)
        self.first.val, self.second.val = self.second.val, self.first.val

Complexity
#

Time O(n), space O(h) for recursion. The follow-up asks for O(1) space, which needs a Morris in-order traversal.

Mistakes to Avoid
#

  • Update second on every inversion. Recording both nodes only at the first inversion swaps the wrong pair when they are not adjacent.
  • Set first only once and never overwrite it.
  • A sentinel prev with value -inf keeps the first node from looking like an inversion.
  • Swap the values; no pointers need to change.

Interview Explanation
#

In-order of a BST is increasing, so a swap creates inversions. If the nodes are not adjacent there are two inversions and the wrong nodes are the earlier one of the first and the later one of the last; if they are adjacent there is a single inversion containing both. I walk in-order, set first = prev at the first inversion, update second = node at every inversion, and swap the two values. Time O(n), space O(h); Morris traversal brings space to O(1).

Related

LeetCode 449: Serialize and Deserialize BST
·2 mins
LeetCode Medium String Tree Depth-First-Search Breadth-First-Search Design Binary-Search-Tree Binary-Tree
LeetCode 449 note: for a BST, pre-order without null markers is enough; deserialize recursively with bounds in O(n)
LeetCode 230: Kth Smallest Element in a BST
·1 min
LeetCode Medium Tree Depth-First-Search Binary-Search-Tree Binary-Tree
LeetCode 230 note: a BST’s in-order traversal is ascending, so stop an iterative in-order walk at the k-th node
LeetCode 98: Validate Binary Search Tree
·3 mins
LeetCode Medium Tree Depth-First-Search Binary-Search-Tree Binary-Tree
LeetCode 98 note: every node has a valid range (low, high); going left the upper bound becomes the node and going right the lower bound does; comparing parent and child is not enough
LeetCode 235: Lowest Common Ancestor of a Binary Search Tree
·2 mins
LeetCode Medium Tree Depth-First-Search Binary-Search-Tree Binary-Tree
LeetCode 235 note: go left when both p and q are smaller, right when both are larger; otherwise (split, or one is the node itself) this node is the LCA
LeetCode 450: Delete Node in a BST
·2 mins
LeetCode Medium Tree Binary-Search-Tree Binary-Tree
LeetCode 450 note: once the node is found: with zero or one child, splice the child in; with two, copy the right subtree’s minimum and delete that node
LeetCode 1372: Longest ZigZag Path in a Binary Tree
·2 mins
LeetCode Medium Dynamic-Programming Tree Depth-First-Search Binary-Tree Dp-on-Trees
LeetCode 1372 note: each node returns two values, the longest zigzag starting left and starting right; going left extends the left child’s start-right value