Talentd
FleetCode
Make and follow sheets.Sign in

Recover Binary Search Tree solution and explanation

MediumBinary Search TreeBinary TreeDepth-First SearchTree6 min read60.9% acceptanceUpdated 9 Apr 2026
Recover Binary Search Tree (with Follow Up) | Live Coding with Explanation | Leetcode #99Algorithms Made Easy · 16:55 · 16K viewsWatch on YouTube
9 more videos on this problem
  1. Recover Binary Search Tree (with Follow Up) | Live Coding with Explanation | Leetcode #99Algorithms Made Easy · 16:55 · 16K views
  2. Leetcode - Recover Binary Search Tree (Python)Timothy H Chang · 5:49 · 9K views
  3. Recover Binary Search Tree | LeetCode 99 | Programming TutorialsProgramming Tutorials · 15:47 · 9K views
  4. Recover Binary Search Tree | Leetcode 99 | BST | Day-19Ayushi Sharma · 15:54 · 7K views
  5. Recover Binary Search Tree | Leet code 99 | Theory explained + Python codeSai Anish Malla · 25:45 · 3K views
  6. LeetCode 99. Recover Binary Search TreeHappy Coding · 48:11 · 1K views
  7. Recover Binary Search Tree | Leetcode 99 | leetcode solutionEasyLeetcode · 10:54 · 707 views
  8. LeetCode 99. Recover Binary Search Tree | JSer - Front-End Interview questionsJSer · 12:36 · 449 views
  9. LeetCode99RecoverBinarySearchTree - Solution to LeetCode 99 - Recover Binary Search TreeLEETCODE MASTER · 14:30 · 349 views
  10. LeetCode 99. [HARD] Recover Binary Search TreeFrancesco Manicardi · 8:48 · 270 views

The problem

You are given the root of a binary search tree (BST), where the values of exactly two nodes of the tree were swapped by mistake. Recover the tree without changing its structure.

Example 1:

Input: root = [1,3,null,null,2]
Output: [3,1,null,null,2]
Explanation: 3 cannot be a left child of 1 because 3 > 1. Swapping 1 and 3 makes the BST valid.

Example 2:

Input: root = [3,1,4,null,null,2]
Output: [2,1,4,null,null,3]
Explanation: 2 cannot be in the right subtree of 3 because 2 < 3. Swapping 2 and 3 makes the BST valid.

Constraints:

  • The number of nodes in the tree is in the range [2, 1000].
  • -231 <= Node.val <= 231 - 1
Follow up: A solution using O(n) space is pretty straight-forward. Could you devise a constant O(1) space solution?

Approach overview

Problem Overview: A valid Binary Search Tree (BST) has an in-order traversal that produces a sorted sequence. In this problem, exactly two nodes in the BST were swapped by mistake. Your task is to restore the tree without changing its structure by identifying those two nodes and swapping their values back.

Approach 1: In-Order Traversal with Additional Space (O(n) time, O(n) space)

A straightforward approach is to perform an in-order traversal and store all node references in an array. Because a correct BST produces a sorted order, any swapped nodes will appear as violations where prev.val > curr.val. Iterate through the collected list and record the two positions where this ordering breaks. The first incorrect node is the larger value from the first violation, and the second node is the smaller value from the last violation. After identifying both nodes, swap their values to recover the BST. This method is simple and easy to reason about but uses O(n) additional memory to store the traversal.

This approach relies heavily on properties of a Binary Search Tree and uses a standard Depth-First Search traversal to collect nodes in sorted order.

Approach 2: Morris Traversal for Constant Space Complexity (O(n) time, O(1) space)

The optimal approach performs the same in-order traversal but without recursion or an auxiliary array. Morris Traversal temporarily modifies the tree structure by creating threaded links to predecessor nodes. While traversing, keep track of the previous visited node and detect ordering violations where prev.val > curr.val. The first time this happens, store prev as the first misplaced node. For the second violation, store curr as the second node. After the traversal finishes, swap the values of these two nodes.

Morris Traversal works because it simulates the call stack used in recursive tree traversal by reusing null pointers as temporary links. Each edge is visited at most twice, keeping the time complexity at O(n) while reducing space usage to O(1). This makes it ideal when memory constraints matter or when interviewers specifically ask for constant space.

Recommended for interviews: Start by explaining the in-order traversal idea since it directly leverages the sorted property of BSTs. That shows you understand the core invariant. Then move to Morris Traversal as the optimized solution with O(1) extra space. Interviewers usually expect the constant-space approach because it demonstrates deeper knowledge of tree traversal techniques.

Approach 1: In-Order Traversal with Additional Space

This approach uses an additional list to store the nodes during an in-order traversal of the BST. The in-order traversal yields the values of the BST in a sorted manner for a correct BST configuration. If two nodes have been swapped, this sorted order will be violated in exactly two places. By storing all nodes during traversal and comparing them, we can identify the two swapped nodes. Once identified, we swap their values to correct the tree.

This method requires O(n) space to store the nodes' values where n is the number of nodes in the tree.

class Solution:
    def recoverTree(self, root: TreeNode) -> None:
        def inorder(node):
            return inorder(node.left) + [node] + inorder(node.right) if node else []
        nodes = inorder(root)
        x = y = None
        for i in range(1, len(nodes)):
            if nodes[i].val < nodes[i - 1].val:
                y = nodes[i]
                if x is None:
                    x = nodes[i - 1]
                else:
                    break
        x.val, y.val = y.val, x.val
import java.util.*;
class Solution {
    public void recoverTree(TreeNode root) {
        List<TreeNode> nodes = new ArrayList<>();
        inorder(root, nodes);
        TreeNode x = null, y = null;
        for (int i = 1; i < nodes.size(); i++) {
            if (nodes.get(i).val < nodes.get(i - 1).val) {
                y = nodes.get(i);
                if (x == null) {
                    x = nodes.get(i - 1);
                } else break;
            }
        }
        int temp = x.val;
        x.val = y.val;
        y.val = temp;
    }
    private void inorder(TreeNode node, List<TreeNode> nodes) {
        if (node == null) return;
        inorder(node.left, nodes);
        nodes.add(node);
        inorder(node.right, nodes);
    }
}
#include <vector>
using namespace std;
class Solution {
public:
    void recoverTree(TreeNode* root) {
        vector<TreeNode*> nodes;
        TreeNode *x = nullptr, *y = nullptr;
        inorder(root, nodes);
        for (int i = 1; i < nodes.size(); ++i) {
            if (nodes[i]->val < nodes[i-1]->val) {
                y = nodes[i];
                if (x == nullptr) x = nodes[i - 1];
                else break;
            }
        }
        swap(x->val, y->val);
    }
    void inorder(TreeNode* node, vector<TreeNode*>& nodes) {
        if (!node) return;
        inorder(node->left, nodes);
        nodes.push_back(node);
        inorder(node->right, nodes);
    }
};
var recoverTree = function(root) {
    const nodes = [];
    inorder(root, nodes);
    let first = null, second = null;
    for (let i = 0; i < nodes.length - 1; i++) {
        if (nodes[i].val > nodes[i + 1].val) {
            second = nodes[i + 1];
            if (!first) first = nodes[i];
            else break;
        }
    }
    [first.val, second.val] = [second.val, first.val];
};
function inorder(node, nodes) {
    if (!node) return;
    inorder(node.left, nodes);
    nodes.push(node);
    inorder(node.right, nodes);
}
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;
void inorder(TreeNode* node, TreeNode** nodes, int* index) {
    if (!node) return;
    inorder(node->left, nodes, index);
    nodes[(*index)++] = node;
    inorder(node->right, nodes, index);
}
void recoverTree(TreeNode* root) {
    TreeNode* nodes[1000];
    int index = 0;
    inorder(root, nodes, &index);
    TreeNode *x = NULL, *y = NULL;
    for (int i = 1; i < index; ++i) {
        if (nodes[i]->val < nodes[i-1]->val) {
            y = nodes[i];
            if (!x) x = nodes[i - 1];
            else break;
        }
    }
    int temp = x->val;
    x->val = y->val;
    y->val = temp;
}
using System.Collections.Generic;
public class Solution {
    public void RecoverTree(TreeNode root) {
        List<TreeNode> nodes = new List<TreeNode>();
        Inorder(root, nodes);
        TreeNode x = null, y = null;
        for (int i = 1; i < nodes.Count; i++) {
            if (nodes[i].val < nodes[i - 1].val) {
                y = nodes[i];
                if (x == null) {
                    x = nodes[i - 1];
                } else break;
            }
        }
        int temp = x.val;
        x.val = y.val;
        y.val = temp;
    }
    private void Inorder(TreeNode node, List<TreeNode> nodes) {
        if (node == null) return;
        Inorder(node.left, nodes);
        nodes.Add(node);
        Inorder(node.right, nodes);
    }
}

This Python solution performs an in-order traversal of the BST and stores the nodes in a list. It then iterates through this list to find the two nodes that are out of order, i.e., the swapped nodes, by checking where the current node value is less than the previous node value. Finally, it swaps the values of these nodes to correct the BST.

Complexity

Time Complexity: O(n) since we are conducting an in-order traversal of the tree.
Space Complexity: O(n) as we store nodes in a list for comparison.

Try this approach in the editor

Approach 2: Morris Traversal for Constant Space Complexity

This approach leverages Morris Traversal to achieve O(1) space complexity, without needing an auxiliary stack or recursion. Morris Traversal utilizes the tree structure itself to keep track of nodes and ensures the tree is reset to its original configuration after traversal. To correct the BST, we detect swapped nodes by identifying violation of BST properties during traversal, and then we swap these nodes to achieve a valid BST.

class Solution:
    def recoverTree(self, root: TreeNode) -> None:
        first = second = prev = None
        current = root
        while current:
            if current.left is None:
                if prev and current.val < prev.val:
                    second = current
                    if first is None:
                        first = prev
                prev = current
                current = current.right
            else:
                pre = current.left
                while pre.right and pre.right != current:
                    pre = pre.right
                if pre.right is None:
                    pre.right = current
                    current = current.left
                else:
                    pre.right = None
                    if prev and current.val < prev.val:
                        second = current
                        if first is None:
                            first = prev
                    prev = current
                    current = current.right
        first.val, second.val = second.val, first.val
class Solution {
    public void recoverTree(TreeNode root) {
        TreeNode first = null, second = null, prev = null;
        TreeNode current = root;
        while (current != null) {
            if (current.left == null) {
                if (prev != null && current.val < prev.val) {
                    second = current;
                    if (first == null) first = prev;
                }
                prev = current;
                current = current.right;
            } else {
                TreeNode pre = current.left;
                while (pre.right != null && pre.right != current)  pre = pre.right;
                if (pre.right == null) {
                    pre.right = current;
                    current = current.left;
                } else {
                    pre.right = null;
                    if (prev != null && current.val < prev.val) {
                        second = current;
                        if (first == null) first = prev;
                    }
                    prev = current;
                    current = current.right;
                }
            }
        }
        int temp = first.val;
        first.val = second.val;
        second.val = temp;
    }
}
class Solution {
public:
    void recoverTree(TreeNode* root) {
        TreeNode *first = nullptr, *second = nullptr, *prev = nullptr;
        TreeNode* current = root;
        while (current) {
            if (!current->left) {
                if (prev && current->val < prev->val) {
                    second = current;
                    if (!first) first = prev;
                }
                prev = current;
                current = current->right;
            } else {
                TreeNode* pre = current->left;
                while (pre->right && pre->right != current) pre = pre->right;
                if (!pre->right) {
                    pre->right = current;
                    current = current->left;
                } else {
                    pre->right = nullptr;
                    if (prev && current->val < prev->val) {
                        second = current;
                        if (!first) first = prev;
                    }
                    prev = current;
                    current = current->right;
                }
            }
        }
        swap(first->val, second->val);
    }
};
function recoverTree(root) {
    let first = null, second = null, prev = null;
    let current = root;
    while (current) {
        if (!current.left) {
            if (prev && current.val < prev.val) {
                second = current;
                if (!first) first = prev;
            }
            prev = current;
            current = current.right;
        } else {
            let pre = current.left;
            while (pre.right && pre.right !== current) pre = pre.right;
            if (!pre.right) {
                pre.right = current;
                current = current.left;
            } else {
                pre.right = null;
                if (prev && current.val < prev.val) {
                    second = current;
                    if (!first) first = prev;
                }
                prev = current;
                current = current.right;
            }
        }
    }
    [first.val, second.val] = [second.val, first.val];
}
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;
void recoverTree(struct TreeNode* root) {
    struct TreeNode *first = NULL, *second = NULL, *prev = NULL;
    struct TreeNode* current = root;
    while (current) {
        if (!current->left) {
            if (prev && current->val < prev->val) {
                second = current;
                if (!first) first = prev;
            }
            prev = current;
            current = current->right;
        } else {
            struct TreeNode* pre = current->left;
            while (pre->right && pre->right != current) pre = pre->right;
            if (!pre->right) {
                pre->right = current;
                current = current->left;
            } else {
                pre->right = NULL;
                if (prev && current->val < prev->val) {
                    second = current;
                    if (!first) first = prev;
                }
                prev = current;
                current = current->right;
            }
        }
    }
    int temp = first->val;
    first->val = second->val;
    second->val = temp;
}
public class Solution {
    public void RecoverTree(TreeNode root) {
        TreeNode first = null, second = null, prev = null;
        TreeNode current = root;
        while (current != null) {
            if (current.left == null) {
                if (prev != null && current.val < prev.val) {
                    second = current;
                    if (first == null) first = prev;
                }
                prev = current;
                current = current.right;
            } else {
                TreeNode pre = current.left;
                while (pre.right != null && pre.right != current) pre = pre.right;
                if (pre.right == null) {
                    pre.right = current;
                    current = current.left;
                } else {
                    pre.right = null;
                    if (prev != null && current.val < prev.val) {
                        second = current;
                        if (first == null) first = prev;
                    }
                    prev = current;
                    current = current.right;
                }
            }
        }
        int temp = first.val;
        first.val = second.val;
        second.val = temp;
    }
}

This Python solution uses Morris Inorder Traversal, which leverages the threads in the tree structure to avoid using additional space. While traversing, we establish temporary links (threads) to visiting nodes using their predecessor relations. We detect unordered node pairs and correct them by swapping their values.

Complexity

Time Complexity: O(n).
Space Complexity: O(1).

Try this approach in the editor

Approach 3: In-order Traversal

In-order traversal of a binary search tree results in an increasing sequence. If two nodes' values are mistakenly swapped, there will definitely be two reverse pairs in the sequence obtained from the in-order traversal. We use first and second to record the smaller and larger values of these two reverse pairs, respectively. Finally, swapping the values of these two nodes will correct the mistake.

The time complexity is O(n), and the space complexity is O(n). Here, n is the number of nodes in the binary search tree.

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func recoverTree(root *TreeNode) {
	var prev, first, second *TreeNode
	var dfs func(*TreeNode)
	dfs = func(root *TreeNode) {
		if root == nil {
			return
		}
		dfs(root.Left)
		if prev != nil && prev.Val > root.Val {
			if first == nil {
				first = prev
			}
			second = root
		}
		prev = root
		dfs(root.Right)
	}
	dfs(root)
	first.Val, second.Val = second.Val, first.Val
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
In-Order Traversal with Additional Space

Time Complexity: O(n) since we are conducting an in-order traversal of the tree.
Space Complexity: O(n) as we store nodes in a list for comparison.

Morris Traversal for Constant Space Complexity

Time Complexity: O(n).
Space Complexity: O(1).

In-order Traversal–

Complexity analysis

ApproachTimeSpaceWhen to Use
In-Order Traversal with ArrayO(n)O(n)Best for clarity and quick implementation when extra memory is acceptable.
Morris Traversal (Constant Space)O(n)O(1)Preferred in interviews when constant auxiliary space is required.

Frequently asked questions

Is Recover Binary Search Tree easy or hard?

Recover Binary Search Tree is rated Medium on LeetCode. Detecting swapped nodes using in-order traversal is straightforward, but implementing the optimal O(1) space Morris Traversal requires deeper understanding of tree traversal techniques.

Recover Binary Search Tree Python/Java solution

Typical Python or Java solutions perform an in-order traversal, track the previous node, and detect two nodes where the sorted order breaks. After traversal, swapping those node values restores the BST in O(n) time.

How to solve Recover Binary Search Tree in O(n)?

Perform an in-order traversal and track the previous visited node. Whenever prev.val is greater than the current node value, record the misplaced nodes. After traversal finishes, swap the values of the two identified nodes to restore the BST.

What is the best approach for Recover Binary Search Tree?

Morris Traversal is considered the best approach because it recovers the BST in O(n) time using O(1) extra space. It performs an in-order traversal without recursion or a stack while detecting the two misplaced nodes through ordering violations.

Is Recover Binary Search Tree asked at Google/Amazon/Meta?

Recover Binary Search Tree is a common interview problem at companies like Amazon, Google, and Meta because it tests understanding of BST properties, in-order traversal, and space optimization techniques like Morris Traversal.

What data structure is used in Recover Binary Search Tree?

The problem operates on a Binary Search Tree. The solution relies on in-order traversal, which can be implemented using recursion, an explicit stack, or Morris Traversal for constant auxiliary space.

What is the time complexity of Recover Binary Search Tree?

Both common solutions run in O(n) time where n is the number of nodes in the tree. Each node is visited at most once during the in-order traversal used to detect the swapped nodes.

Comments

Now write it yourselfClose this page and solve Recover Binary Search Tree in the editor, without looking.
Practise Recover Binary Search Tree