Source
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 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 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 first tree to second)
Take all elements of 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 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 first tree.
Method 2 (Merge Inorder Traversals)
1) Do inorder traversal of first tree and store the traversal in one temp array arr1[]. This step takes O(m) time.
2) Do inorder traversal of second tree and store the traversal in another temp array arr2[]. This step takes O(n) time.
3) The arrays created in step 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.
4) Construct a balanced tree from the merged array using the technique discussed in
this post. This step takes O(m+n) time.
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 C++ implementation of this method.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* left;
struct node* right;
};
|
int *merge(int arr1[], int arr2[], int m, int n);
void storeInorder(struct node* node, int inorder[], int *index_ptr);
struct node* sortedArrayToBST(int arr[], int start, int end);
struct node* mergeTrees(struct node *root1, struct node *root2, int m, int n)
{
int *arr1 = new int[m];
int i = 0;
storeInorder(root1, arr1, &i);
int *arr2 = new int[n];
int j = 0;
storeInorder(root2, arr2, &j);
int *mergedArr = merge(arr1, arr2, m, n);
return sortedArrayToBST (mergedArr, 0, m+n-1);
}
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);
}
void printInorder(struct node* node)
{
if (node == NULL)
return;
printInorder(node->left);
printf("%d ", node->data);
printInorder(node->right);
}
int *merge(int arr1[], int arr2[], int m, int n)
{
int *mergedArr = new int[m + n];
int i = 0, j = 0, k = 0;
while (i < m && j < n)
{
if (arr1[i] < arr2[j])
{
mergedArr[k] = arr1[i];
i++;
}
else
{
mergedArr[k] = arr2[j];
j++;
}
k++;
}
while (i < m)
{
mergedArr[k] = arr1[i];
i++; k++;
}
while (j < n)
{
mergedArr[k] = arr2[j];
j++; k++;
}
return mergedArr;
}
void storeInorder(struct node* node, int inorder[], int *index_ptr)
{
if (node == NULL)
return;
storeInorder(node->left, inorder, index_ptr);
inorder[*index_ptr] = node->data;
(*index_ptr)++;
storeInorder(node->right, inorder, index_ptr);
}
struct node* sortedArrayToBST(int arr[], int start, int end)
{
if (start > end)
return NULL;
int mid = (start + end)/2;
struct node *root = newNode(arr[mid]);
root->left = sortedArrayToBST(arr, start, mid-1);
root->right = sortedArrayToBST(arr, mid+1, end);
return root;
}