# Recover Binary Search Tree

Difficulty Level Hard
Frequently asked in Amazon ByteDance Microsoft Oracle Uber
Binary Search Tree Binary Tree Depth First Search TreeViews 1350

Consider a binary search tree, two nodes of the tree have been swapped, design an algorithm to recover the binary search Tree.

Example

Consider the binary search tree given below whose two nodes have been swapped as input. Incorrect nodes on the BST are detected(highlighted) and then swapped to obtain the correct BST. Below is the corrected output BST obtained after swapping the incorrect nodes. ### Types of Solution for Recover Binary Search Tree

1. Naive
2. Recursive
3. Iterative
4. Morris Traversal

### Naive

#### Approach for Recover Binary Search Tree

Use vector to store all the elements of the tree using inorder traversal, sort this vector. Again, Perform inorder traversal of the tree and assign values from sorted vector to tree nodes one by one.

#### Algorithm

1. Perform inorder traversal of the tree and store the traversal in a dynamic array.
2. Sort the dynamic array using insertion sort(for minimum complexity).
3. Perform the inorder traversal again and change the node values to values from the sorted array.
4. Return the root node of the corrected binary search tree. #### Implementation

##### C++ Program
```#include <iostream>
#include <bits/stdc++.h>
using namespace std;

// blueprint of the tree node
class Node
{
public :
int data;
Node *left, *right, *next;

Node(int key)
{
data = key;
left = right = next = NULL;
}
};

// function that performs inorder traversal based on the mode
/*
Their are 3 modes :
1. traversal ('t') : simply perform traversal
2. storage ('s') : store data of tree into a vector
3. modify ('m'): store data of vector into a tree
*/
void inorder(Node *root,vector <int> &arr,char mode)
{
if(!root)
return;

inorder(root->left,arr,mode);
if(mode == 't')
cout<<root->data<<" ";
else if(mode == 's')
arr.push_back(root->data);
else if(mode == 'm')
{
int n = arr.size();
root->data = arr[n-1];
arr.pop_back();
}
inorder(root->right,arr,mode);
}

// function that corrects the BST and returns it's root
Node* fixBST(Node *root)
{
// array to store inorder traversal
vector <int> arr;
// store the inorder traversal into arr
inorder(root,arr,'s');

// apply insertion sort to arr
// insertion sort is used to minimize time complexity to o(n)
int i,j,key;
for (i = 1; i < arr.size(); i++)
{
key = arr[i];
j = i - 1;
while (j >= 0 && arr[j] < key)
{
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}

// perform inorder on tree and modify the the node value of tree
inorder(root,arr,'m');
return root;
}

int main()
{
/* create the incorrect BST*/
Node *root = new Node(4);
root->left = new Node(7);
root->right = new Node(6);
root->left->left = new Node(1);
root->left->right = new Node(3);
root->right->left = new Node(5);
root->right->right = new Node(2);

vector <int> arr;

cout<<"Inorder traversal before : ";
inorder(root,arr,'t');

root = fixBST(root);

cout<<endl;

cout<<"Inorder traversal after : ";
inorder(root,arr,'t');
return 0;
}```
```Inorder traversal before : 1 7 3 4 5 6 2
Inorder traversal after : 1 2 3 4 5 6 7```
##### Java Program
```import java.util.*;
import java.io.*;

class tutorialCup
{
// blueprint of the tree node
static class Node
{
int data;
Node left, right, next;

Node(int key)
{
data = key;
left = right = next = null;
}
}

// function that performs inorder traversal based on the mode
/*
Their are 3 modes :
1. traversal ('t') : simply perform traversal
2. storage ('s') : store data of tree into a vector
3. modify ('m'): store data of vector into a tree
*/
static void inorder(Node root,ArrayList <Integer> arr,char mode)
{
if(root == null)
return;

inorder(root.left,arr,mode);
if(mode == 't')
System.out.print(root.data+" ");
else if(mode == 's')
else if(mode == 'm')
{
int n = arr.size();
root.data = arr.get(n-1);
arr.remove(n-1);
}
inorder(root.right,arr,mode);
}

// function that corrects the BST and returns it's root
static Node fixBST(Node root)
{
// array to store inorder traversal
ArrayList <Integer> arr = new ArrayList<>();
// store the inorder traversal into arr
inorder(root,arr,'s');

// apply insertion sort to arr
// insertion sort is used to minimize time complexity to o(n)
int i,j,key;
for (i = 1; i < arr.size(); i++)
{
key = arr.get(i);
j = i - 1;
while (j >= 0 && arr.get(j) < key)
{
arr.set(j+1,arr.get(j));
j = j - 1;
}
arr.set(j+1,key);
}

// perform inorder on tree and modify the the node value of tree
inorder(root,arr,'m');
return root;
}

public static void main (String[] args)
{
/* create the incorrect BST*/
Node root = new Node(4);
root.left = new Node(7);
root.right = new Node(6);
root.left.left = new Node(1);
root.left.right = new Node(3);
root.right.left = new Node(5);
root.right.right = new Node(2);

ArrayList <Integer> arr = new ArrayList<>();

System.out.print("Inorder traversal before : ");
inorder(root,arr,'t');

root = fixBST(root);

System.out.println();
System.out.print("Inorder traversal after : ");
inorder(root,arr,'t');
}

}```
```Inorder traversal before : 1 7 3 4 5 6 2
Inorder traversal after : 1 2 3 4 5 6 7```

#### Complexity Analysis for Recover Binary Search Tree

• Time Complexity : T(n) = O(n)
• Space Complexity : A(n) = O(n)

### Recursive

#### Approach for Recover Binary Search Tree

1. Consider the Tree given in the above example. The nodes of the BST can be swapped in two ways.
2. 1st way: 2 non-adjacent tree nodes are swapped (i.e. these nodes have at least one node between them. for ex: inorder traversal of the tree where non-adjacent nodes are swapped is: 1 7 3 4 5 6 2. As we observe 2 and 7 are swapped from their respective positions.
1. We perform the inorder traversal and use first and second variables to store the two incorrectly placed nodes. we use prev to store the previous node visited before the current (root) node during inorder traversal.
2. During inorder traversal, we find a node that violates the BST order. i.e. prev->data > root->data(where root is the current node being visited), we store prev into first and root into second.
3. During further traversal, if we find another node that violates the BST criteria (as mentioned above), but this time the first node has been already assigned a value. so we assign the current node to second.
4. After the traversal is over, we swap the data stored in the first and second nodes.
3. 2nd way: 2 adjacent nodes are swapped (i.e. the nodes are parent-child pair).for ex: inorder traversal of the tree where adjacent nodes are swapped is: 1 2 4 3 5 6 7. As we observe 3 and 4 are swapped from their respective positions.
1. We perform the inorder traversal and use first and second variables to store the two incorrectly placed nodes. we use prev to store the previous node visited before the current (root) node during inorder traversal.
2. During inorder traversal, we find a node that violates the BST order. i.e. prev->data > root->data(where root is the current node being visited), we store prev into first and root into second.
3. After the traversal is over, we swap the data stored in the first and second nodes.

#### Algorithm

1. Define prev(stores previous nodes in traversal), first(stores first node out of order), second(stores second node out of order) variables to store various tree node addresses.
2. Perform simple inorder traversal.
3. If during inorder traversal, we find a node that violates the BST order. i.e. prev->data > root->data.we store prev into first and root into second.
4. During further traversal, if we find another node that violates the BST criteria,i.e. prev->data > root->data. but this time the first node had been already assigned a value. so we assign the current node to second.
5. After execution of inorder traversal. swap the data of first and second nodes.The tree is fixed. #### Implementation

##### C++ Program
```#include <iostream>
#include <bits/stdc++.h>
using namespace std;

// blueprint of the tree node
class Node
{
public :
int data;
Node *left, *right, *next;

Node(int key)
{
data = key;
left = right = next = NULL;
}
};
/* function that performs inorder traversal
and checks for the incorrectly set nodes*/
void inorderFix(Node *root,Node* &prev,Node* &first,Node* &second)
{
if(root == NULL)
return;

inorderFix(root->left,prev,first,second);

if(prev != NULL && prev->data > root->data)
{
// first misordering found
if(first == NULL)
{
first = prev;
second = root;
}

// second misordering found (if exists)
else
second = root;
}

prev = root;

inorderFix(root->right,prev,first,second);
}
// function that corrects the BST and returns it's root
Node* fixBST(Node *root)
{
Node *prev,*first,*second;
prev = first = second = NULL;

inorderFix(root,prev,first,second);
swap(first->data,second->data);

return root;
}

// function to simply perform inorder traversal of the tree
void inorder(Node *root)
{
if(root == NULL)
return;

inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}

int main()
{
/* create the incorrect BST*/
Node *root = new Node(4);
root->left = new Node(7);
root->right = new Node(6);
root->left->left = new Node(1);
root->left->right = new Node(3);
root->right->left = new Node(5);
root->right->right = new Node(2);

cout<<"Inorder traversal before : ";
inorder(root);

root = fixBST(root);
cout<<endl;

cout<<"Inorder traversal after : ";
inorder(root);

return 0;
}```
```Inorder Traversal before : 1 7 3 4 5 6 2
Inorder Traversal after : 1 2 3 4 5 6 7```
##### Java Program
```import java.util.*;
import java.io.*;

class tutorialCup
{
// blueprint of the tree node
static class Node
{
int data;
Node left, right, next;

Node(int key)
{
data = key;
left = right = next = null;
}
}

/* function that performs inorder traversal
and checks for the incorrectly set nodes*/
static void inorderFix(Node root,ArrayList <Node> nodes)
{
if(root == null)
return;

inorderFix(root.left,nodes);

if(nodes.get(0) != null && nodes.get(0).data > root.data)
{
// first misordering found
if(nodes.get(1) == null)
{
// first is set to previous
nodes.set(1,nodes.get(0));
// second is set to current node
nodes.set(2,root);
}
// second misordering found (if exists)
else
nodes.set(2,root);
}

// 1st element of ArrayList stores previous nodes
nodes.set(0,root);

inorderFix(root.right,nodes);
}
// function that corrects the BST and returns it's root
/*
here,
prev -> nodes.get(0)
first -> nodes.get(1)
second -> nodes.get(2)
*/
static Node fixBST(Node root)
{
// we use ArrayList to store previous(nodes),first(nodes) and second(nodes)
// initially all nodes are set to null
ArrayList <Node> nodes = new ArrayList<>(Arrays.asList(null,null,null));
inorderFix(root,nodes);

// swap the values of the nodes
int temp = nodes.get(1).data;
nodes.get(1).data = nodes.get(2).data;
nodes.get(2).data = temp;

return root;
}

// function to simply perform inorder traversal of the tree
static void inorder(Node root)
{
if(root == null)
return;

inorder(root.left);
System.out.print(root.data+" ");
inorder(root.right);
}

public static void main (String[] args)
{
/* create the incorrect BST*/
Node root = new Node(4);
root.left = new Node(7);
root.right = new Node(6);
root.left.left = new Node(1);
root.left.right = new Node(3);
root.right.left = new Node(5);
root.right.right = new Node(2);

System.out.print("Inorder Traversal before : ");
inorder(root);

root = fixBST(root);
System.out.println();

System.out.print("Inorder Traversal after : ");
inorder(root);

}
}```
```Inorder Traversal before : 1 7 3 4 5 6 2
Inorder Traversal after : 1 2 3 4 5 6 7```

#### Complexity Analysis for Recover Binary Search Tree

• Time Complexity : T(n) = O(n)
• Space Complexity : A(n) = O(n), recursion stack space used.

### Iterative

#### Approach for Recover Binary Search Tree

The idea is to convert the above recursive code into an iterative code.

#### Algorithm

1. Define prev(stores previous nodes in traversal), first(stores first node out of order), second(stores second node out of order) variables to store various tree node addresses.
2. Perform simple inorder traversal.
3. If during inorder traversal, we find a node that violates the BST order. i.e. prev->data > root->data.we store prev into first and root into second.
4. During further traversal, if we find another node that violates the BST criteria,i.e. prev->data > root->data. but this time the first node had been already assigned a value. so we assign the current node to second.
5. After execution of inorder traversal. swap the data of the first and second nodes. The tree is fixed. #### Implementation

##### C++ Program
```#include <iostream>
#include <bits/stdc++.h>
using namespace std;

// blueprint of the tree node
class Node
{
public :
int data;
Node *left, *right, *next;

Node(int key)
{
data = key;
left = right = next = NULL;
}
};

// function that corrects the BST by performing iterative inorder
// and returns it's root
Node* fixBST(Node *root)
{
Node *prev,*first,*second;
prev = first = second = NULL;

Node* curr = root;

stack <Node*> st;

while(!st.empty() ||  root != NULL)
{
if(root != NULL)
{
// visit current node's (root) left subtree
st.push(root);
root = root->left;
}
else
{
// done left subtree of current node
root = st.top();
st.pop();

// compare root.val with root.val if we have one
if(prev != NULL && root->data < prev->data)
{
// incorrect smaller node is always found as prev node
if(first == NULL)
first = prev;

// incorrect larger node is always found as current root node
second = root;
}

// visit root's right subtree
prev = root;
root = root->right;
}
}

// fix the BST by swapping values
int temp = first->data;
first->data = second->data;
second->data = temp;

// return address of the original root node
return curr;
}

// function to simply perform inorder traversal of the tree
void inorder(Node *root)
{
if(root == NULL)
return;

inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}

int main()
{
/* create the incorrect BST*/
Node *root = new Node(4);
root->left = new Node(7);
root->right = new Node(6);
root->left->left = new Node(1);
root->left->right = new Node(3);
root->right->left = new Node(5);
root->right->right = new Node(2);

cout<<"Inorder traversal before : ";
inorder(root);

root = fixBST(root);
cout<<endl;

cout<<"Inorder traversal after : ";
inorder(root);

return 0;
}```
```Inorder Traversal before : 1 7 3 4 5 6 2
Inorder Traversal after : 1 2 3 4 5 6 7```
##### Java Program
```import java.util.*;
import java.io.*;

class tutorialCup
{
// blueprint of the tree node
static class Node
{
int data;
Node left, right, next;

Node(int key)
{
data = key;
left = right = next = null;
}
}

// function that corrects the BST and returns it's root
static Node fixBST(Node root)
{
Node prev,first,second;
prev = first = second = null;

Node curr = root;

Stack<Node> st = new Stack<Node>();

while(!st.isEmpty() ||  root != null)
{
if(root != null)
{
// visit current node's (root) left subtree
st.push(root);
root = root.left;
}
else
{
// done left subtree of current node
root = st.pop();

// compare root.val with root.val if we have one
if(prev != null && root.data <= prev.data)
{
// incorrect smaller node is always found as prev node
if(first == null)
first = prev;

// incorrect larger node is always found as current root node
second = root;
}

// visit root's right subtree
prev = root;
root = root.right;
}
}

// fix the BST by swapping values
int temp = first.data;
first.data = second.data;
second.data = temp;

// return address of the original root node
return curr;
}

// function to simply perform inorder traversal of the tree
static void inorder(Node root)
{
if(root == null)
return;

inorder(root.left);
System.out.print(root.data+" ");
inorder(root.right);
}

public static void main (String[] args)
{
/* create the incorrect BST*/
Node root = new Node(4);
root.left = new Node(7);
root.right = new Node(6);
root.left.left = new Node(1);
root.left.right = new Node(3);
root.right.left = new Node(5);
root.right.right = new Node(2);

System.out.print("Inorder Traversal before : ");
inorder(root);

root = fixBST(root);
System.out.println();

System.out.print("Inorder Traversal after : ");
inorder(root);
}
}```
```Inorder Traversal before : 1 7 3 4 5 6 2
Inorder Traversal after : 1 2 3 4 5 6 7```

#### Complexity Analysis for Recover Binary Search Tree

• Time Complexity : T(n) = O(n)
• Space Complexity : A(n) = O(n)

### Morris Traversal

#### Approach for Recover Binary Search Tree

The idea is to basically perform inorder Morris traversal of the tree. Morris traversal ensures that traversal takes place in linear time and constant space (not even recursion stack space).

Morris traversal is similar to recursive/iterative traversal, but we need to modify the tree structure during the traversal. before visiting the left tree of a root, we will build a back-edge between a rightmost node in the left tree and the root. So we can go back to the root node after we are done with traversing the left tree.

Then we locate the rightmost node in the left subtree again, cut the back-edge, recover the tree structure, and start visit the right subtree.

The detection of incorrect tree nodes is similar to the recursion/iteration case.

#### Algorithm

1. Perform Morris traversal and process each node in inorder fashion.
2. For every node (except the leftmost node of the tree), keep track of its previous node in prev. The current node being processed is stored in the curr.
3. If during the traversal, we find a node that violates the BST order. i.e. prev->data > root->data.we store prev into first and root into second.
4. During further traversal, if we find another node that violates the BST criteria,i.e. prev->data > root->data. but since, the first node had been already assigned a value. so we assign the current node(which violates BST criteria) to second.
5. After execution of inorder traversal. swap the data of first and second nodes and The tree gets fixed. #### Implementation

##### C++ Program
```#include <iostream>
#include <bits/stdc++.h>
using namespace std;

// blueprint of the tree node
class Node
{
public :
int data;
Node *left, *right, *next;

Node(int key)
{
data = key;
left = right = next = NULL;
}
};

// function that corrects the BST by performing iterative inorder
// and returns it's root
Node* fixBST(Node *root)
{
Node *prev,*first,*second;
prev = first = second = NULL;

// stores rightmost node in left subtree of root
Node* rightMost = NULL;
// stores current node starting with root node
Node* curr = root;

while(curr != NULL)
{
// for each node, we compare it with prev node as we did in in-order-traversal
if(prev != NULL && curr->data < prev->data)
{
if(first == NULL)
first = prev;

second = curr;
}

if(curr->left != NULL)
{
// got left tree, then let's locate its rightmost node in left tree
rightMost = curr->left;
// we may have visited the left tree before, and connect the rightmost node with curr node (root node)
while(rightMost->right != NULL && rightMost->right != curr)
rightMost = rightMost->right;

if(rightMost->right == curr)
{
// if this left tree has been visited before, then we are done with it
// cut the connection with currNode and start visit curr's right tree
rightMost->right = NULL;
prev = curr;
curr = curr->right;
}
else
{
// if this left tree has not been visited before, then we create a back edge from rightmost node
// to curr node, so we can return to the start point after done the left tree
rightMost->right = curr;
curr = curr->left;
}

}
else
{
// no left tree, then just visit its right tree
prev = curr;
curr = curr->right;
}
}

// swap the values of incorrect nodes
swap(first->data,second->data);
return root;
}

// function to simply perform inorder traversal of the tree
void inorder(Node *root)
{
if(root == NULL)
return;

inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}

int main()
{
/* create the incorrect BST*/
Node *root = new Node(4);
root->left = new Node(7);
root->right = new Node(6);
root->left->left = new Node(1);
root->left->right = new Node(3);
root->right->left = new Node(5);
root->right->right = new Node(2);

cout<<"Inorder traversal before : ";
inorder(root);

root = fixBST(root);
cout<<endl;

cout<<"Inorder traversal after : ";
inorder(root);

return 0;
}```
```Inorder Traversal before : 1 7 3 4 5 6 2
Inorder Traversal after : 1 2 3 4 5 6 7```
##### Java Program
```import java.util.*;
import java.io.*;

class tutorialCup
{
// blueprint of the tree node
static class Node
{
int data;
Node left, right, next;

Node(int key)
{
data = key;
left = right = next = null;
}
}

// function that corrects the BST using morris traversal and returns it's root
static Node fixBST(Node root)
{
Node prev,first,second;
prev = first = second = null;

// stores rightmost node in left subtree of root
Node rightMost = null;
// stores current node starting with root node
Node curr = root;

while(curr != null)
{
// for each node, we compare it with prev node as we did in in-order-traversal
if(prev != null && curr.data < prev.data)
{
if(first == null)
first = prev;

second = curr;
}

if(curr.left != null)
{
// got left tree, then let's locate its rightmost node in left tree
rightMost = curr.left;
// we may have visited the left tree before, and connect the rightmost node with curr node (root node)
while(rightMost.right != null && rightMost.right != curr)
rightMost = rightMost.right;

if(rightMost.right == curr)
{
// if this left tree has been visited before, then we are done with it
// cut the connection with currNode and start visit curr's right tree
rightMost.right = null;
prev = curr;
curr = curr.right;
}
else
{
// if this left tree has not been visited before, then we create a back edge from rightmost node
// to curr node, so we can return to the start point after done the left tree
rightMost.right = curr;
curr = curr.left;
}

}
else
{
// no left tree, then just visit its right tree
prev = curr;
curr = curr.right;
}
}

// swap the values of incorrect nodes
int temp = first.data;
first.data = second.data;
second.data = temp;

return root;
}

// function to simply perform inorder traversal of the tree
static void inorder(Node root)
{
if(root == null)
return;

inorder(root.left);
System.out.print(root.data+" ");
inorder(root.right);
}

public static void main (String[] args)
{
/* create the incorrect BST*/
Node root = new Node(4);
root.left = new Node(7);
root.right = new Node(6);
root.left.left = new Node(1);
root.left.right = new Node(3);
root.right.left = new Node(5);
root.right.right = new Node(2);

System.out.print("Inorder Traversal before : ");
inorder(root);

// fixing the BST
root = fixBST(root);
System.out.println();

System.out.print("Inorder Traversal after : ");
inorder(root);
}
}```
```Inorder Traversal before : 1 7 3 4 5 6 2
Inorder Traversal after : 1 2 3 4 5 6 7```

#### Complexity Analysis for Recover Binary Search Tree

1. Time Complexity : T(n) = O(n)
2. Space Complexity : A(n) = O(1), nor data structure neither recursion stack space used.

References

Translate »