You are given two balanced binary search trees e.g., AVL or Red-Black Tree. Write a function that merges the two given balanced BSTs into a balanced binary search tree. Let there be m elements in the first tree and n elements in the other tree. Your merge function should take O(m+n) time.
In the following solutions, it is assumed that the sizes of trees are also given as input. If the size is not given, then we can get the size by traversing the tree (See this).
Method 1 (Insert elements of the first tree to the second):
Take all elements of the first BST one by one, and insert them into the second BST. Inserting an element to a self-balancing BST takes Logn time (See this) where n is the size of the BST. So time complexity of this method is Log(n) + Log(n+1) … Log(m+n-1). The value of this expression will be between mLogn and mLog(m+n-1). As an optimization, we can pick the smaller tree as the first tree.
Method 2 (Merge Inorder Traversals):
- Do inorder traversal of the first tree and store the traversal in one temp array arr1[]. This step takes O(m) time.Â
- Do inorder traversal of the second tree and store the traversal in another temp array arr2[]. This step takes O(n) time.Â
- The arrays created in steps 1 and 2 are sorted arrays. Merge the two sorted arrays into one array of size m + n. This step takes O(m+n) time.Â
- Construct a balanced tree from the merged array using the technique discussed in this post. This step takes O(m+n) time.
The time complexity of this method is O(m+n) which is better than method 1. This method takes O(m+n) time even if the input BSTs are not balanced.Â
Following is the implementation of this method.
C++
// C++ program to Merge Two Balanced Binary Search Trees #include<bits/stdc++.h> using namespace std; Â
/* A binary tree node has data, pointer to left child and a pointer to right child */ class node { Â Â Â Â public : Â Â Â Â int data; Â Â Â Â node* left; Â Â Â Â node* right; }; Â
// A utility function to merge two sorted arrays into one int *merge( int arr1[], int arr2[], int m, int n); Â
// A helper function that stores inorder // traversal of a tree in inorder array void storeInorder(node* node, int inorder[], Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int *index_ptr); Â
/* A function that constructs Balanced Binary Search Tree from a sorted array node* sortedArrayToBST( int arr[], int start, int end); Â
/* This function merges two balanced BSTs with roots as root1 and root2. m and n are the sizes of the trees respectively */ node* mergeTrees(node *root1, node *root2, int m, int n) {     // Store inorder traversal of     // first tree in an array arr1[]     int *arr1 = new int [m];     int i = 0;     storeInorder(root1, arr1, &i); Â
    // Store inorder traversal of second     // tree in another array arr2[]     int *arr2 = new int [n];     int j = 0;     storeInorder(root2, arr2, &j); Â
    // Merge the two sorted array into one     int *mergedArr = merge(arr1, arr2, m, n); Â
    // Construct a tree from the merged     // array and return root of the tree     return sortedArrayToBST (mergedArr, 0, m + n - 1); } Â
/* Helper function that allocates a new node with the given data and NULL left and right pointers. */ node* newNode( int data) { Â Â Â Â node* Node = new node(); Â Â Â Â Node->data = data; Â Â Â Â Node->left = NULL; Â Â Â Â Node->right = NULL; Â
    return (Node); } Â
// A utility function to print inorder // traversal of a given binary tree void printInorder(node* node) { Â Â Â Â if (node == NULL) Â Â Â Â Â Â Â Â return ; Â
    /* first recur on left child */     printInorder(node->left); Â
    cout << node->data << " " ; Â
    /* now recur on right child */     printInorder(node->right); } Â
// A utility function to merge // two sorted arrays into one int *merge( int arr1[], int arr2[], int m, int n) {     // mergedArr[] is going to contain result     int *mergedArr = new int [m + n];     int i = 0, j = 0, k = 0; Â
    // Traverse through both arrays     while (i < m && j < n)     {         // Pick the smaller element and put it in mergedArr         if (arr1[i] < arr2[j])         {             mergedArr[k] = arr1[i];             i++;         }         else         {             mergedArr[k] = arr2[j];             j++;         }         k++;     } Â
    // If there are more elements in first array     while (i < m)     {         mergedArr[k] = arr1[i];         i++; k++;     } Â
    // If there are more elements in second array     while (j < n)     {         mergedArr[k] = arr2[j];         j++; k++;     } Â
    return mergedArr; } Â
// A helper function that stores inorder // traversal of a tree rooted with node void storeInorder(node* node, int inorder[], int *index_ptr) { Â Â Â Â if (node == NULL) Â Â Â Â Â Â Â Â return ; Â
    /* first recur on left child */     storeInorder(node->left, inorder, index_ptr); Â
    inorder[*index_ptr] = node->data;     (*index_ptr)++; // increase index for next entry Â
    /* now recur on right child */     storeInorder(node->right, inorder, index_ptr); } Â
/* A function that constructs Balanced // Binary Search Tree from a sorted array node* sortedArrayToBST( int arr[], int start, int end) { Â Â Â Â /* Base Case */ Â Â Â Â if (start > end) Â Â Â Â return NULL; Â
    /* Get the middle element and make it root */     int mid = (start + end)/2;     node *root = newNode(arr[mid]); Â
    /* Recursively construct the left subtree and make it     left child of root */     root->left = sortedArrayToBST(arr, start, mid-1); Â
    /* Recursively construct the right subtree and make it     right child of root */     root->right = sortedArrayToBST(arr, mid+1, end); Â
    return root; } Â
/* Driver code*/ int main() {     /* Create following tree as first balanced BST         100         / \         50 300     / \     20 70     */     node *root1 = newNode(100);     root1->left    = newNode(50);     root1->right = newNode(300);     root1->left->left = newNode(20);     root1->left->right = newNode(70); Â
    /* Create following tree as second balanced BST             80         / \         40 120     */     node *root2 = newNode(80);     root2->left    = newNode(40);     root2->right = newNode(120); Â
    node *mergedTree = mergeTrees(root1, root2, 5, 3); Â
    cout << "Following is Inorder traversal of the merged tree \n" ;     printInorder(mergedTree); Â
    return 0; } Â
// This code is contributed by rathbhupendra |
C
// C program to Merge Two Balanced Binary Search Trees #include <stdio.h> #include <stdlib.h> Â
/* A binary tree node has data, pointer to left child    and a pointer to right child */ struct node {     int data;     struct node* left;     struct node* right; }; Â
// A utility function to merge two sorted arrays into one int *merge( int arr1[], int arr2[], int m, int n); Â
// A helper function that stores inorder traversal of a tree in inorder array void storeInorder( struct node* node, int inorder[], int *index_ptr); Â
/* A function that constructs Balanced Binary Search Tree from a sorted array struct node* sortedArrayToBST( int arr[], int start, int end); Â
/* This function merges two balanced BSTs with roots as root1 and root2. Â Â Â m and n are the sizes of the trees respectively */ struct node* mergeTrees( struct node *root1, struct node *root2, int m, int n) { Â Â Â Â // Store inorder traversal of first tree in an array arr1[] Â Â Â Â int *arr1 = new int [m]; Â Â Â Â int i = 0; Â Â Â Â storeInorder(root1, arr1, &i); Â
    // Store inorder traversal of second tree in another array arr2[]     int *arr2 = new int [n];     int j = 0;     storeInorder(root2, arr2, &j); Â
    // Merge the two sorted array into one     int *mergedArr = merge(arr1, arr2, m, n); Â
    // Construct a tree from the merged array and return root of the tree     return sortedArrayToBST (mergedArr, 0, m+n-1); } Â
/* Helper function that allocates a new node with the    given data and NULL left and right pointers. */ struct node* newNode( int data) {     struct node* node = ( struct node*)                         malloc ( sizeof ( struct node));     node->data = data;     node->left = NULL;     node->right = NULL; Â
    return (node); } Â
// A utility function to print inorder traversal of a given binary tree void printInorder( struct node* node) { Â Â Â Â if (node == NULL) Â Â Â Â Â Â Â Â return ; Â
    /* first recur on left child */     printInorder(node->left); Â
    printf ( "%d " , node->data); Â
    /* now recur on right child */     printInorder(node->right); } Â
// A utility function to merge two sorted arrays into one int *merge( int arr1[], int arr2[], int m, int n) {     // mergedArr[] is going to contain result     int *mergedArr = new int [m + n];     int i = 0, j = 0, k = 0; Â
    // Traverse through both arrays     while (i < m && j < n)     {         // Pick the smaller element and put it in mergedArr         if (arr1[i] < arr2[j])         {             mergedArr[k] = arr1[i];             i++;         }         else         {             mergedArr[k] = arr2[j];             j++;         }         k++;     } Â
    // If there are more elements in first array     while (i < m)     {         mergedArr[k] = arr1[i];         i++; k++;     } Â
    // If there are more elements in second array     while (j < n)     {         mergedArr[k] = arr2[j];         j++; k++;     } Â
    return mergedArr; } Â
// A helper function that stores inorder traversal of a tree rooted with node void storeInorder( struct node* node, int inorder[], int *index_ptr) { Â Â Â Â if (node == NULL) Â Â Â Â Â Â Â Â return ; Â
    /* first recur on left child */     storeInorder(node->left, inorder, index_ptr); Â
    inorder[*index_ptr] = node->data;     (*index_ptr)++; // increase index for next entry Â
    /* now recur on right child */     storeInorder(node->right, inorder, index_ptr); } Â
/* A function that constructs Balanced Binary Search Tree from a sorted array struct node* sortedArrayToBST( int arr[], int start, int end) { Â Â Â Â /* Base Case */ Â Â Â Â if (start > end) Â Â Â Â Â Â return NULL; Â
    /* Get the middle element and make it root */     int mid = (start + end)/2;     struct node *root = newNode(arr[mid]); Â
    /* Recursively construct the left subtree and make it        left child of root */     root->left = sortedArrayToBST(arr, start, mid-1); Â
    /* Recursively construct the right subtree and make it        right child of root */     root->right = sortedArrayToBST(arr, mid+1, end); Â
    return root; } Â
/* Driver program to test above functions*/ int main() {     /* Create following tree as first balanced BST            100           / \         50   300        / \       20 70     */     struct node *root1 = newNode(100);     root1->left        = newNode(50);     root1->right       = newNode(300);     root1->left->left  = newNode(20);     root1->left->right = newNode(70); Â
    /* Create following tree as second balanced BST             80            / \          40  120     */     struct node *root2 = newNode(80);     root2->left        = newNode(40);     root2->right       = newNode(120); Â
    struct node *mergedTree = mergeTrees(root1, root2, 5, 3); Â
    printf ( "Following is Inorder traversal of the merged tree \n" );     printInorder(mergedTree); Â
    getchar ();     return 0; } |
Java
// Java program to Merge Two Balanced Binary Search Trees import java.io.*; import java.util.ArrayList; Â
// A binary tree node class Node { Â Â Â Â Â Â Â Â Â int data; Â Â Â Â Node left, right; Â Â Â Â Â Â Â Â Â Node( int d) { Â Â Â Â Â Â Â Â data = d; Â Â Â Â Â Â Â Â left = right = null ; Â Â Â Â } } Â
class BinarySearchTree { Â Â Â Â Â Â Â Â Â // Root of BST Â Â Â Â Node root; Â
    // Constructor     BinarySearchTree() {         root = null ;     }          // Inorder traversal of the tree     void inorder()     {         inorderUtil( this .root);     }      // Utility function for inorder traversal of the tree void inorderUtil(Node node) {     if (node== null )         return ;              inorderUtil(node.left);     System.out.print(node.data + " " );     inorderUtil(node.right); }      Â
    // A Utility Method that stores inorder traversal of a tree     public ArrayList<Integer> storeInorderUtil(Node node, ArrayList<Integer> list)     {         if (node == null )             return list;                  //recur on the left child         storeInorderUtil(node.left, list);                  // Adds data to the list         list.add(node.data);                  //recur on the right child         storeInorderUtil(node.right, list);                  return list;     }          // Method that stores inorder traversal of a tree     ArrayList<Integer> storeInorder(Node node)     {         ArrayList<Integer> list1 = new ArrayList<>();         ArrayList<Integer> list2 = storeInorderUtil(node,list1);         return list2;     } Â
    // Method that merges two ArrayLists into one.     ArrayList<Integer> merge(ArrayList<Integer>list1, ArrayList<Integer>list2, int m, int n)     {         // list3 will contain the merge of list1 and list2         ArrayList<Integer> list3 = new ArrayList<>();         int i= 0 ;         int j= 0 ;                  //Traversing through both ArrayLists         while ( i<m && j<n)         {             // Smaller one goes into list3             if (list1.get(i)<list2.get(j))             {                 list3.add(list1.get(i));                 i++;             }             else             {                 list3.add(list2.get(j));                 j++;             }         }                  // Adds the remaining elements of list1 into list3         while (i<m)         {             list3.add(list1.get(i));             i++;         }              // Adds the remaining elements of list2 into list3         while (j<n)         {             list3.add(list2.get(j));             j++;         }         return list3;     }          // Method that converts an ArrayList to a BST     Node ALtoBST(ArrayList<Integer>list, int start, int end)     {         // Base case         if (start > end)             return null ;              // Get the middle element and make it root            int mid = (start+end)/ 2 ;         Node node = new Node(list.get(mid)); Â
        /* Recursively construct the left subtree and make it         left child of root */         node.left = ALtoBST(list, start, mid- 1 );                  /* Recursively construct the right subtree and make it         right child of root */         node.right = ALtoBST(list, mid+ 1 , end);          return node;     }          // Method that merges two trees into a single one.     Node mergeTrees(Node node1, Node node2)     {         //Stores Inorder of tree1 to list1         ArrayList<Integer>list1 = storeInorder(node1);                  //Stores Inorder of tree2 to list2         ArrayList<Integer>list2 = storeInorder(node2);                  // Merges both list1 and list2 into list3         ArrayList<Integer>list3 = merge(list1, list2, list1.size(), list2.size());                  //Eventually converts the merged list into resultant BST         Node node = ALtoBST(list3, 0 , list3.size()- 1 );         return node;     } Â
    // Driver function     public static void main (String[] args)     {                  /* Creating following tree as First balanced BST                 100                 / \                 50 300                 / \                20 70         */                  BinarySearchTree tree1 = new BinarySearchTree();         tree1.root = new Node( 100 );         tree1.root.left = new Node( 50 );         tree1.root.right = new Node( 300 );         tree1.root.left.left = new Node( 20 );         tree1.root.left.right = new Node( 70 );                  /* Creating following tree as second balanced BST                 80                 / \               40 120         */                      BinarySearchTree tree2 = new BinarySearchTree();         tree2.root = new Node( 80 );           tree2.root.left = new Node( 40 );         tree2.root.right = new Node( 120 );                                   BinarySearchTree tree = new BinarySearchTree();           tree.root = tree.mergeTrees(tree1.root, tree2.root);         System.out.println( "The Inorder traversal of the merged BST is: " );         tree.inorder();     } } // This code has been contributed by Kamal Rawal |
Python3
# A binary tree node has data, pointer to left child # and a pointer to right child class Node:     def __init__( self , val):         self .val = val         self .left = None         self .right = None Â
# A utility function to merge two sorted arrays into one # Time Complexity of below function: O(m + n) # Space Complexity of below function: O(m + n) def merge_sorted_arr(arr1, arr2): Â Â Â Â arr = [] Â Â Â Â i = j = 0 Â Â Â Â while i < len (arr1) and j < len (arr2): Â Â Â Â Â Â Â Â if arr1[i] < = arr2[j]: Â Â Â Â Â Â Â Â Â Â Â Â arr.append(arr1[i]) Â Â Â Â Â Â Â Â Â Â Â Â i + = 1 Â Â Â Â Â Â Â Â else : Â Â Â Â Â Â Â Â Â Â Â Â arr.append(arr2[j]) Â Â Â Â Â Â Â Â Â Â Â Â j + = 1 Â Â Â Â while i < len (arr1): Â Â Â Â Â Â Â Â arr.append(arr1[i]) Â Â Â Â Â Â Â Â i + = 1 Â Â Â Â while i < len (arr2): Â Â Â Â Â Â Â Â arr.append(arr2[j]) Â Â Â Â Â Â Â Â j + = 1 Â Â Â Â return arr Â
# A helper function that stores inorder # traversal of a tree in arr def inorder(root, arr = []): Â Â Â Â if root: Â Â Â Â Â Â Â Â inorder(root.left, arr) Â Â Â Â Â Â Â Â arr.append(root.val) Â Â Â Â Â Â Â Â inorder(root.right, arr) Â
# A utility function to insert the values # in the individual Tree def insert(root, val):     if not root:         return Node(val)     if root.val = = val:         return root     elif root.val > val:         root.left = insert(root.left, val)     else :         root.right = insert(root.right, val)     return root Â
# Converts the merged array to a balanced BST # Explanation of the below code: def arr_to_bst(arr):     if not arr:         return None     mid = len (arr) / / 2     root = Node(arr[mid])     root.left = arr_to_bst(arr[:mid])     root.right = arr_to_bst(arr[mid + 1 :])     return root Â
if __name__ = = '__main__' :     root1 = root2 = None          # Inserting values in first tree     root1 = insert(root1, 100 )     root1 = insert(root1, 50 )     root1 = insert(root1, 300 )     root1 = insert(root1, 20 )     root1 = insert(root1, 70 )          # Inserting values in second tree     root2 = insert(root2, 80 )     root2 = insert(root2, 40 )     root2 = insert(root2, 120 )     arr1 = []     inorder(root1, arr1)     arr2 = []     inorder(root2, arr2)     arr = merge_sorted_arr(arr1, arr2)     root = arr_to_bst(arr)     res = []     inorder(root, res)     print ( 'Following is Inorder traversal of the merged tree' )     for i in res:       print (i, end = ' ' )        # This code is contributed by Flarow4 |
C#
// C# program to Merge Two Balanced Binary Search Trees using System; using System.Collections.Generic; Â
// A binary tree node public class Node { Â
    public int data;     public Node left, right; Â
    public Node( int d)     {         data = d;         left = right = null ;     } } Â
public class BinarySearchTree { Â
    // Root of BST     public Node root; Â
    // Constructor     public BinarySearchTree()     {         root = null ;     } Â
    // Inorder traversal of the tree     public virtual void inorder()     {         inorderUtil( this .root);     } Â
// Utility function for inorder traversal of the tree public virtual void inorderUtil(Node node) { Â Â Â Â if (node == null ) Â Â Â Â { Â Â Â Â Â Â Â Â return ; Â Â Â Â } Â
    inorderUtil(node.left);     Console.Write(node.data + " " );     inorderUtil(node.right); } Â
Â
    // A Utility Method that stores inorder traversal of a tree     public virtual List< int > storeInorderUtil(Node node, List< int > list)     {         if (node == null )         {             return list;         } Â
        //recur on the left child         storeInorderUtil(node.left, list); Â
        // Adds data to the list         list.Add(node.data); Â
        //recur on the right child         storeInorderUtil(node.right, list); Â
        return list;     } Â
    // Method that stores inorder traversal of a tree     public virtual List< int > storeInorder(Node node)     {         List< int > list1 = new List< int >();         List< int > list2 = storeInorderUtil(node,list1);         return list2;     } Â
    // Method that merges two ArrayLists into one.     public virtual List< int > merge(List< int > list1, List< int > list2, int m, int n)     {         // list3 will contain the merge of list1 and list2         List< int > list3 = new List< int >();         int i = 0;         int j = 0; Â
        //Traversing through both ArrayLists         while (i < m && j < n)         {             // Smaller one goes into list3             if (list1[i] < list2[j])             {                 list3.Add(list1[i]);                 i++;             }             else             {                 list3.Add(list2[j]);                 j++;             }         } Â
        // Adds the remaining elements of list1 into list3         while (i < m)         {             list3.Add(list1[i]);             i++;         } Â
        // Adds the remaining elements of list2 into list3         while (j < n)         {             list3.Add(list2[j]);             j++;         }         return list3;     } Â
    // Method that converts an ArrayList to a BST     public virtual Node ALtoBST(List< int > list, int start, int end)     {         // Base case         if (start > end)         {             return null ;         } Â
        // Get the middle element and make it root             int mid = (start + end) / 2;         Node node = new Node(list[mid]); Â
        /* Recursively construct the left subtree and make it         left child of root */         node.left = ALtoBST(list, start, mid - 1); Â
        /* Recursively construct the right subtree and make it         right child of root */         node.right = ALtoBST(list, mid + 1, end); Â
    return node;     } Â
    // Method that merges two trees into a single one.     public virtual Node mergeTrees(Node node1, Node node2)     {         //Stores Inorder of tree1 to list1         List< int > list1 = storeInorder(node1); Â
        //Stores Inorder of tree2 to list2         List< int > list2 = storeInorder(node2); Â
        // Merges both list1 and list2 into list3         List< int > list3 = merge(list1, list2, list1.Count, list2.Count); Â
        //Eventually converts the merged list into resultant BST         Node node = ALtoBST(list3, 0, list3.Count - 1);         return node;     } Â
    // Driver function     public static void Main( string [] args)     { Â
        /* Creating following tree as First balanced BST                 100                 / \                 50 300                 / \                20 70         */ Â
        BinarySearchTree tree1 = new BinarySearchTree();         tree1.root = new Node(100);         tree1.root.left = new Node(50);         tree1.root.right = new Node(300);         tree1.root.left.left = new Node(20);         tree1.root.left.right = new Node(70); Â
        /* Creating following tree as second balanced BST                 80                 / \               40 120         */ Â
        BinarySearchTree tree2 = new BinarySearchTree();         tree2.root = new Node(80);         tree2.root.left = new Node(40);         tree2.root.right = new Node(120); Â
Â
        BinarySearchTree tree = new BinarySearchTree();         tree.root = tree.mergeTrees(tree1.root, tree2.root);         Console.WriteLine( "The Inorder traversal of the merged BST is: " );         tree.inorder();     } } Â
  // This code is contributed by Shrikant13 |
Javascript
<script> Â
      // JavaScript program to Merge Two       // Balanced Binary Search Trees       // A binary tree node       class Node {         constructor(d) {           this .data = d;           this .left = null ;           this .right = null ;         }       } Â
      class BinarySearchTree {         // Constructor         constructor() {           this .root = null ;         } Â
        // Inorder traversal of the tree         inorder() {           this .inorderUtil( this .root);         } Â
        // Utility function for inorder traversal of the tree         inorderUtil(node) {           if (node == null ) {             return ;           } Â
          this .inorderUtil(node.left);           document.write(node.data + " " );           this .inorderUtil(node.right);         } Â
        // A Utility Method that stores         // inorder traversal of a tree         storeInorderUtil(node, list) {           if (node == null ) {             return list;           } Â
          //recur on the left child           this .storeInorderUtil(node.left, list); Â
          // Adds data to the list           list.push(node.data); Â
          //recur on the right child           this .storeInorderUtil(node.right, list); Â
          return list;         } Â
        // Method that stores inorder traversal of a tree         storeInorder(node) {           var list1 = [];           var list2 = this .storeInorderUtil(node, list1);           return list2;         } Â
        // Method that merges two ArrayLists into one.         merge(list1, list2, m, n) {           // list3 will contain the merge of list1 and list2           var list3 = [];           var i = 0;           var j = 0; Â
          //Traversing through both ArrayLists           while (i < m && j < n) {             // Smaller one goes into list3             if (list1[i] < list2[j]) {               list3.push(list1[i]);               i++;             } else {               list3.push(list2[j]);               j++;             }           } Â
          // Adds the remaining elements of list1 into list3           while (i < m) {             list3.push(list1[i]);             i++;           } Â
          // Adds the remaining elements of list2 into list3           while (j < n) {             list3.push(list2[j]);             j++;           }           return list3;         } Â
        // Method that converts an ArrayList to a BST         ALtoBST(list, start, end) {           // Base case           if (start > end) {             return null ;           } Â
          // Get the middle element and make it root           var mid = parseInt((start + end) / 2);           var node = new Node(list[mid]); Â
          /* Recursively construct the left subtree and make it         left child of root */           node.left = this .ALtoBST(list, start, mid - 1); Â
          /* Recursively construct the right subtree and make it         right child of root */           node.right = this .ALtoBST(list, mid + 1, end); Â
          return node;         } Â
        // Method that merges two trees into a single one.         mergeTrees(node1, node2) {           //Stores Inorder of tree1 to list1           var list1 = this .storeInorder(node1); Â
          //Stores Inorder of tree2 to list2           var list2 = this .storeInorder(node2); Â
          // Merges both list1 and list2 into list3           var list3 =           this .merge(list1, list2, list1.length, list2.length); Â
          //Eventually converts the merged list into resultant BST           var node = this .ALtoBST(list3, 0, list3.length - 1);           return node;         }       }       // Driver function       /* Creating following tree as First balanced BST                 100                 / \                 50 300                 / \             20 70         */ Â
      var tree1 = new BinarySearchTree();       tree1.root = new Node(100);       tree1.root.left = new Node(50);       tree1.root.right = new Node(300);       tree1.root.left.left = new Node(20);       tree1.root.left.right = new Node(70); Â
      /* Creating following tree as second balanced BST                 80                 / \             40 120         */ Â
      var tree2 = new BinarySearchTree();       tree2.root = new Node(80);       tree2.root.left = new Node(40);       tree2.root.right = new Node(120); Â
      var tree = new BinarySearchTree();       tree.root = tree.mergeTrees(tree1.root, tree2.root);       document.write(       "Following is Inorder traversal of the merged tree <br>"       );       tree.inorder();        </script> |
Following is Inorder traversal of the merged tree 20 40 50 70 80 100 120 300
 Time complexity: O(m+n), where m and n are the numbers of elements in the two binary search trees.
 Space complexity: O(m+n). This is because we need to allocate space for the two arrays that store the elements from the two binary search trees, as well as an array to store the merged elements.
Method 3 (In-Place Merge using DLL):
We can use a Doubly Linked List to merge trees in place. Following are the steps.
- Convert the given two Binary Search Trees into a doubly linked list in place (Refer to this post for this step).Â
- Merge the two sorted Linked Lists (Refer to this post for this step).Â
- Build a Balanced Binary Search Tree from the merged list created in step 2. (Refer to this post for this step)
The time complexity of this method is also O(m+n) and this method does conversion in place.
Thanks to Dheeraj and Ronzii for suggesting this method.
C++
// C++ Code for the above approach Â
#include <bits/stdc++.h> using namespace std; Â
/* A binary tree node has data, a pointer to left child and a pointer to right child */ class Node { public : Â Â Â Â int data; Â Â Â Â Node* left; Â Â Â Â Node* right; }; Â
// Function to return a new Node Node* newNode( int data) { Â Â Â Â Node* node = new Node(); Â Â Â Â node->data = data; Â Â Â Â node->left = NULL; Â Â Â Â node->right = NULL; Â
    return (node); } Â
// Function to convert bst to // a doubly linked list void bstTodll(Node* root, Node*& head) { Â Â Â Â // if root is NULL Â Â Â Â if (!root) Â Â Â Â Â Â Â Â return ; Â
    // Convert right subtree recursively     bstTodll(root->right, head); Â
    // Update root     root->right = head; Â
    // if head is not NULL     if (head) { Â
        // Update left of the head         head->left = root;     } Â
    // Update head     head = root; Â
    // Convert left subtree recursively     bstTodll(root->left, head); } Â
// Function to merge two sorted linked list Node* mergeLinkedList(Node* head1, Node* head2) { Â
    /*Create head and tail for result list*/     Node* head = NULL;     Node* tail = NULL; Â
    while (head1 && head2) { Â
        if (head1->data < head2->data) { Â
            if (!head)                 head = head1;             else { Â
                tail->right = head1;                 head1->left = tail;             } Â
            tail = head1;             head1 = head1->right;         } Â
        else { Â
            if (!head)                 head = head2;             else {                 tail->right = head2;                 head2->left = tail;             } Â
            tail = head2;             head2 = head2->right;         }     } Â
    while (head1) {         tail->right = head1;         head1->left = tail;         tail = head1;         head1 = head1->right;     } Â
    while (head2) {         tail->right = head2;         head2->left = tail;         tail = head2;         head2 = head2->right;     } Â
    // Return the created DLL     return head; } Â
// function to convert list to bst Node* sortedListToBST(Node*& head, int n) {     // if no element is left or head is null     if (n <= 0 || !head)         return NULL; Â
    // Create left part from the list recursively     Node* left = sortedListToBST(head, n / 2); Â
    Node* root = head;     root->left = left;     head = head->right; Â
    // Create left part from the list recursively     root->right = sortedListToBST(head, n - (n / 2) - 1); Â
    // Return the root of BST     return root; } Â
// This function merges two balanced BSTs Node* mergeTrees(Node* root1, Node* root2, int m, int n) { Â Â Â Â // Convert BSTs into sorted Doubly Linked Lists Â
    Node* head1 = NULL;     bstTodll(root1, head1);     head1->left = NULL; Â
    Node* head2 = NULL;     bstTodll(root2, head2);     head2->left = NULL; Â
    // Merge the two sorted lists into one     Node* head = mergeLinkedList(head1, head2); Â
    // Construct a tree from the merged lists     return sortedListToBST(head, m + n); } Â
void printInorder(Node* node) { Â Â Â Â // if current node is NULL Â Â Â Â if (!node) { Â Â Â Â Â Â Â Â return ; Â Â Â Â } Â
    printInorder(node->left); Â
      // Print node of current data     cout << node->data << " " ; Â
    printInorder(node->right); } Â
/* Driver code*/ int main() { Â Â Â Â /* Create following tree as first balanced BST Â Â Â Â Â Â Â 100 Â Â Â Â Â Â Â / \ Â Â Â Â Â Â 50 300 Â Â Â Â Â / \ Â Â Â Â 20 70Â Â */ Â
    Node* root1 = newNode(100);     root1->left = newNode(50);     root1->right = newNode(300);     root1->left->left = newNode(20);     root1->left->right = newNode(70); Â
    /* Create following tree as second balanced BST              80             / \            40 120     */     Node* root2 = newNode(80);     root2->left = newNode(40);     root2->right = newNode(120); Â
      // Function Call     Node* mergedTree = mergeTrees(root1, root2, 5, 3); Â
    cout << "Following is Inorder traversal of the merged "             "tree \n" ;     printInorder(mergedTree); Â
    return 0; } Â
// This code is contributed by Tapesh(tapeshdua420) |
Java
// Java Code for the above approach import java.util.*; Â
/* A binary tree node has data, a pointer to left child and a pointer to right child */ class Node { Â Â Â Â int data; Â Â Â Â Node left, right; Â
    Node( int d)     {         data = d;         left = right = null ;     } } Â
// Function to return a new Node public class Main { Â
    Node newNode( int data)     {         Node node = new Node(data);         node.left = null ;         node.right = null ;         return (node);     } Â
    // Function to convert bst to a doubly linked list     void bstTodll(Node root, Node[] head)     { Â
        // if root is NULL         if (root == null )             return ; Â
        // Convert right subtree recursively         bstTodll(root.right, head); Â
        // Update root         root.right = head[ 0 ]; Â
        // if head is not NULL         if (head[ 0 ] != null ) { Â
            // Update left of the head             head[ 0 ].left = root;         } Â
        // Update head         head[ 0 ] = root; Â
        // Convert left subtree recursively         bstTodll(root.left, head);     } Â
    // Function to merge two sorted linked list     Node mergeLinkedList(Node head1, Node head2)     { Â
        /*Create head and tail for result list*/         Node head = null , tail = null ;         while (head1 != null && head2 != null ) {             if (head1.data < head2.data) {                 if (head == null ) {                     head = head1;                 }                 else {                     tail.right = head1;                     head1.left = tail;                 }                 tail = head1;                 head1 = head1.right;             }             else {                 if (head == null ) {                     head = head2;                 }                 else {                     tail.right = head2;                     head2.left = tail;                 }                 tail = head2;                 head2 = head2.right;             }         }         while (head1 != null ) {             tail.right = head1;             head1.left = tail;             tail = head1;             head1 = head1.right;         }         while (head2 != null ) {             tail.right = head2;             head2.left = tail;             tail = head2;             head2 = head2.right;         } Â
        // Return the created DLL         return head;     } Â
    // function to convert list to bst     Node sortedListToBST(Node[] head, int n)     { Â
        // if no element is left or head is null         if (n <= 0 || head[ 0 ] == null )             return null ; Â
        // Create left part from the list recursively         Node left = sortedListToBST(head, n / 2 );         Node root = head[ 0 ];         root.left = left;         head[ 0 ] = head[ 0 ].right; Â
        // Create left part from the list recursively         root.right = sortedListToBST(head, n - (n / 2 ) - 1 ); Â
        // Return the root of BST         return root;     } Â
    // This function merges two balanced BSTs     Node mergeTrees(Node root1, Node root2, int m, int n)     { Â
        // Convert BSTs into sorted Doubly Linked Lists Â
        Node[] head1 = new Node[ 1 ];         head1[ 0 ] = null ;         bstTodll(root1, head1);         head1[ 0 ].left = null ; Â
        Node[] head2 = new Node[ 1 ];         head2[ 0 ] = null ;         bstTodll(root2, head2);         head2[ 0 ].left = null ; Â
        // Merge the two sorted lists into one         Node head = mergeLinkedList(head1[ 0 ], head2[ 0 ]); Â
        // Construct a tree from the merged lists         return sortedListToBST( new Node[] { head }, m + n);     } Â
    void printInorder(Node node)     { Â
        // if current node is NULL         if (node == null ) {             return ;         }         printInorder(node.left); Â
        // Print node of current data         System.out.print(node.data + " " ); Â
        printInorder(node.right);     } Â
    /* Driver code*/     public static void main(String[] args)     {         Main obj = new Main(); Â
        /* Create following tree as first balanced BST            100            / \           50 300          / \         20 70  */ Â
        Node root1 = obj.newNode( 100 );         root1.left = obj.newNode( 50 );         root1.right = obj.newNode( 300 );         root1.left.left = obj.newNode( 20 );         root1.left.right = obj.newNode( 70 ); Â
        /* Create following tree as second balanced BST                 80                / \               40 120        */ Â
        Node root2 = obj.newNode( 80 );         root2.left = obj.newNode( 40 );         root2.right = obj.newNode( 120 ); Â
        // Function Call         Node mergedTree             = obj.mergeTrees(root1, root2, 5 , 3 ); Â
        System.out.println(             "Following is Inorder traversal of the merged tree:" );         obj.printInorder(mergedTree);     } } |
Python
class TreeNode:     def __init__( self , data):         self .data = data         self .left = None         self .right = None Â
class Solution: Â Â Â Â def __init__( self ): Â Â Â Â Â Â Â Â self .head1 = [ None ] Â Â Â Â Â Â Â Â self .head2 = [ None ] Â
    def newNode( self , data):         node = TreeNode(data)         node.left = None         node.right = None         return node Â
    def bstToDLL( self , root, head):         if not root:             return Â
        self .bstToDLL(root.right, head) Â
        root.right = head[ 0 ] Â
        if head[ 0 ]:             head[ 0 ].left = root Â
        head[ 0 ] = root Â
        self .bstToDLL(root.left, head) Â
    def mergeLinkedList( self , head1, head2):         head = None         tail = None Â
        while head1 and head2:             if head1.data < head2.data:                 if not head:                     head = head1                 else :                     tail.right = head1                     head1.left = tail                 tail = head1                 head1 = head1.right             else :                 if not head:                     head = head2                 else :                     tail.right = head2                     head2.left = tail                 tail = head2                 head2 = head2.right Â
        while head1:             tail.right = head1             head1.left = tail             tail = head1             head1 = head1.right Â
        while head2:             tail.right = head2             head2.left = tail             tail = head2             head2 = head2.right Â
        return head Â
    def sortedListToBST( self , head, n):         if n < = 0 or not head[ 0 ]:             return None Â
        left = self .sortedListToBST(head, n / / 2 )         root = head[ 0 ]         root.left = left         head[ 0 ] = head[ 0 ].right Â
        root.right = self .sortedListToBST(head, n - (n / / 2 ) - 1 ) Â
        return root Â
    def mergeTrees( self , root1, root2, m, n):         self .bstToDLL(root1, self .head1)         self .head1[ 0 ].left = None Â
        self .bstToDLL(root2, self .head2)         self .head2[ 0 ].left = None Â
        merged_head = self .mergeLinkedList( self .head1[ 0 ], self .head2[ 0 ]) Â
        merged_root = self .sortedListToBST([merged_head], m + n) Â
        return merged_root Â
    def printInorder( self , node):         if not node:             return         self .printInorder(node.left)         print (node.data),         self .printInorder(node.right) Â
# Create the first balanced BST root1 = TreeNode( 100 ) root1.left = TreeNode( 50 ) root1.right = TreeNode( 300 ) root1.left.left = TreeNode( 20 ) root1.left.right = TreeNode( 70 ) Â
# Create the second balanced BST root2 = TreeNode( 80 ) root2.left = TreeNode( 40 ) root2.right = TreeNode( 120 ) Â
solution = Solution() mergedTree = solution.mergeTrees(root1, root2, 5 , 3 ) Â
print ( "Inorder traversal of the merged tree:" ) solution.printInorder(mergedTree) |
C#
// C# Code for the above approach using System; Â
/* A binary tree node has data, a pointer to left child and a pointer to right child */ public class Node { Â Â public int data; Â Â public Node left; Â Â public Node right; } Â
public class Program {   // Function to return a new Node   static Node newNode( int data)   {     Node node = new Node();     node.data = data;     node.left = null ;     node.right = null ; Â
    return node;   } Â
  // Function to convert bst to   // a doubly linked list   static void bstTodll(Node root, ref Node head)   {     // if root is NUL     if (root == null )       return ; Â
    // Convert right subtree recursively     bstTodll(root.right, ref head); Â
    // Update root     root.right = head; Â
    // if head is not NULL     if (head != null ) Â
      // Update left of the head       head.left = root; Â
    // Update head     head = root; Â
    // Convert left subtree recursively     bstTodll(root.left, ref head);   } Â
  // Function to merge two sorted linked list   static Node mergeLinkedList(Node head1, Node head2)   {     /*Create head and tail for result list*/     Node head = null , tail = null ; Â
    while (head1 != null && head2 != null ) {       if (head1.data < head2.data) {         if (head == null )           head = head1;         else {           tail.right = head1;           head1.left = tail;         } Â
        tail = head1;         head1 = head1.right;       }       else {         if (head == null )           head = head2;         else {           tail.right = head2;           head2.left = tail;         } Â
        tail = head2;         head2 = head2.right;       }     } Â
    while (head1 != null ) {       tail.right = head1;       head1.left = tail;       tail = head1;       head1 = head1.right;     } Â
    while (head2 != null ) {       tail.right = head2;       head2.left = tail;       tail = head2;       head2 = head2.right;     } Â
    // Return the created DLL     return head;   } Â
  // function to convert list to bst   static Node sortedListToBST( ref Node head, int n)   {     // if no element is left or head is null     if (n <= 0 || head == null )       return null ;     // Create left part from the list recursively     Node left = sortedListToBST( ref head, n / 2); Â
    Node root = head;     root.left = left;     head = head.right; Â
    // Create left part from the list recursively     root.right       = sortedListToBST( ref head, n - (n / 2) - 1); Â
    // Return the root of BST     return root;   } Â
  // This function merges two balanced BSTs Â
  static Node mergeTrees(Node root1, Node root2, int m,                          int n)   {     // Convert BSTs into sorted Doubly Linked Lists     Node head1 = null ;     bstTodll(root1, ref head1);     head1.left = null ; Â
    Node head2 = null ;     bstTodll(root2, ref head2);     head2.left = null ; Â
    // Merge the two sorted lists into one     Node head = mergeLinkedList(head1, head2); Â
    // Construct a tree from the merged lists     return sortedListToBST( ref head, m + n);   } Â
  static void printInorder(Node node)   {     // if current node is NULL     if (node == null )       return ; Â
    printInorder(node.left); Â
    // Print node of current data     Console.Write(node.data + " " );     printInorder(node.right);   } Â
  /* Driver code*/   public static void Main()   { Â
    /* Create following tree as first balanced BST            100            / \           50 300          / \         20 70  */     Node root1 = newNode(100);     root1.left = newNode(50);     root1.right = newNode(300);     root1.left.left = newNode(20);     root1.left.right = newNode(70); Â
    /* Create following tree as second balanced BST                  80                 / \                40 120         */     Node root2 = newNode(80);     root2.left = newNode(40);     root2.right = newNode(120); Â
    // Function Call     Node mergedTree = mergeTrees(root1, root2, 5, 3); Â
    Console.WriteLine(       "Following is Inorder traversal of the merged tree: " );     printInorder(mergedTree);   }   // This code is contributed by rutikbhosale } |
Javascript
// JavaScrpit Code for above approach Â
// A binary tree node has data, // a pointer to left child, // and a pointer to right child class Node { Â Â Â Â constructor(data) { Â Â Â Â Â Â Â Â this .data = data; Â Â Â Â Â Â Â Â this .left = null ; Â Â Â Â Â Â Â Â this .right = null ; Â Â Â Â } } Â
// Function to convert BST to a doubly linked list function bstToDll(root, headRef) { Â Â Â Â if (!root) { Â Â Â Â Â Â Â Â return ; Â Â Â Â } Â
    // Convert right subtree recursively     bstToDll(root.right, headRef); Â
    // Update root     root.right = headRef.node; Â
    // Update left of the head if head is not null     if (headRef.node) {         headRef.node.left = root;     } Â
    // Update head     headRef.node = root; Â
    // Convert left subtree recursively     bstToDll(root.left, headRef); } Â
// Function to merge two sorted linked lists function mergeLinkedList(head1, head2) { Â Â Â Â let head = null ; Â Â Â Â let tail = null ; Â
    while (head1 && head2) {         if (head1.data < head2.data) {             if (!head) {                 head = head1;             } else {                 tail.right = head1;                 head1.left = tail;             }             tail = head1;             head1 = head1.right;         } else {             if (!head) {                 head = head2;             } else {                 tail.right = head2;                 head2.left = tail;             }             tail = head2;             head2 = head2.right;         }     } Â
    while (head1) {         tail.right = head1;         head1.left = tail;         tail = head1;         head1 = head1.right;     } Â
    while (head2) {         tail.right = head2;         head2.left = tail;         tail = head2;         head2 = head2.right;     } Â
    // Return the created DLL     return head; } Â
// Function to convert a sorted linked list to a BST function sortedListToBST(headRef, n) { Â Â Â Â if (n <= 0 || !headRef.node) { Â Â Â Â Â Â Â Â return null ; Â Â Â Â } Â
    // Create the left part from the list recursively     const left = sortedListToBST(headRef, Math.floor(n / 2)); Â
    const root = headRef.node;     root.left = left;     headRef.node = headRef.node.right; Â
    // Create the right part from the list recursively     root.right = sortedListToBST(headRef, n - Math.floor(n / 2) - 1); Â
    // Return the root of the BST     return root; } Â
// This function merges two balanced BSTs function mergeTrees(root1, root2, m, n) {     // Convert BSTs into sorted Doubly Linked Lists     const headRef1 = { node: null };     bstToDll(root1, headRef1);     headRef1.node.left = null ; Â
    const headRef2 = { node: null };     bstToDll(root2, headRef2);     headRef2.node.left = null ; Â
    // Merge the two sorted lists into one     const mergedHead = mergeLinkedList(headRef1.node, headRef2.node); Â
    // Construct a tree from the merged lists     return sortedListToBST({ node: mergedHead }, m + n); } Â
function printInorder(node) { Â Â Â Â if (!node) { Â Â Â Â Â Â Â Â return ; Â Â Â Â } Â
    printInorder(node.left);     console.log(node.data);     printInorder(node.right); } Â
// Driver code // Create the first balanced BST const root1 = new Node(100); root1.left = new Node(50); root1.right = new Node(300); root1.left.left = new Node(20); root1.left.right = new Node(70); Â
// Create the second balanced BST const root2 = new Node(80); root2.left = new Node(40); root2.right = new Node(120); Â
// Function call to merge the trees const mergedTree = mergeTrees(root1, root2, 5, 3); Â
console.log( "Following is Inorder traversal of the merged tree:" ); printInorder(mergedTree); |
Following is Inorder traversal of the merged tree 20 40 50 70 80 100 120 300
Time Complexity: O(N + M). where N and M are the numbers of nodes in the given trees.
Auxiliary Space: O(1), as constant extra space is used.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!