Print Common Nodes in Two Binary Search Trees
Given two Binary Search Trees, find common nodes in them. In other words, find intersection of two BSTs.
Method 1 (Simple Solution) A simple way is to one by once search every node of first tree in second tree. Time complexity of this solution is O(m * h) where m is number of nodes in first tree and h is height of second tree.
Method 2:
- Approach – If we think of another problem in which we are given two sorted arrays and we have to find the intersection between them, we can do it easily using two pointer technique. Now we can easily convert this problem into above. We know that if we store the inorder traversal of a BST in an array, that array will be sorted in ascending order. So what we can do is simply take the inorder traversal of both the trees and store them in two separate arrays and then find intersection between two arrays.
- Algorithm –
1) Do inorder traversal of first tree and store the traversal in an auxiliary array ar1[]. See sortedInorder() here.
2) Do inorder traversal of second tree and store the traversal in an auxiliary array ar2[]
3) Find intersection of ar1[] and ar2[]. See this for details. - Complexity Analysis:
- Time Complexity: O(m+n).
Here ‘m’ and ‘n’ are number of nodes in first and second tree respectively,as we need to traverse both the trees. - Auxiliary Space :No use of any data structure for storing values-: O(m+n)
The reason is that we need two separate arrays for storing inorder traversals of both the trees.
- Time Complexity: O(m+n).
- Approach:
The idea here is to optimize the space. In the above approach we store all the elements of the tree and then compare but the question is it really necessary to store all the elements. What one can do is store a particular branch of the tree (worst case ‘Height of the tree’) and then start comparing. We can take two stacks and store inorder traversal of trees in respective stacks but the maximum number of elements should be equal to that particular branch of the tree. As soon as that branch ends we start popping and comparing the elements of the stack. Now if top(stack-1)<top(stack-2) there can be more elements in the right branch of top(stack-1) which are greater than it and can be equal to top(stack-2). So we insert right branch of top(stack-1) till it is equal to NULL. At the end of each such insertion we have three conditions to check and then we do the insertions in the stack accordingly.if top(stack-1)<top(stack-2) root1=root1->right (then do insertions) if top(stack-1)>top(stack-2) root2=root2->right (then do insertions) else It's a match
Method 3 (Linear Time and limited Extra Space)
The idea is to use iterative inorder traversal
C++
// C++ program of iterative traversal based method to // find common elements in two BSTs. #include<iostream> #include<stack> using namespace std; // A BST node struct Node { int key; struct Node *left, *right; }; // A utility function to create a new node Node *newNode( int ele) { Node *temp = new Node; temp->key = ele; temp->left = temp->right = NULL; return temp; } // Function two print common elements in given two trees void printCommon(Node *root1, Node *root2) { // Create two stacks for two inorder traversals stack<Node *> stack1, s1, s2; while (1) { // push the Nodes of first tree in stack s1 if (root1) { s1.push(root1); root1 = root1->left; } // push the Nodes of second tree in stack s2 else if (root2) { s2.push(root2); root2 = root2->left; } // Both root1 and root2 are NULL here else if (!s1.empty() && !s2.empty()) { root1 = s1.top(); root2 = s2.top(); // If current keys in two trees are same if (root1->key == root2->key) { cout << root1->key << " " ; s1.pop(); s2.pop(); // move to the inorder successor root1 = root1->right; root2 = root2->right; } else if (root1->key < root2->key) { // If Node of first tree is smaller, than that of // second tree, then its obvious that the inorder // successors of current Node can have same value // as that of the second tree Node. Thus, we pop // from s2 s1.pop(); root1 = root1->right; // root2 is set to NULL, because we need // new Nodes of tree 1 root2 = NULL; } else if (root1->key > root2->key) { s2.pop(); root2 = root2->right; root1 = NULL; } } // Both roots and both stacks are empty else break ; } } // A utility function to do inorder traversal void inorder( struct Node *root) { if (root) { inorder(root->left); cout<<root->key<< " " ; inorder(root->right); } } /* A utility function to insert a new Node with given key in BST */ struct Node* insert( struct Node* node, int key) { /* If the tree is empty, return a new Node */ if (node == NULL) return newNode(key); /* Otherwise, recur down the tree */ if (key < node->key) node->left = insert(node->left, key); else if (key > node->key) node->right = insert(node->right, key); /* return the (unchanged) Node pointer */ return node; } // Driver program int main() { // Create first tree as shown in example Node *root1 = NULL; root1 = insert(root1, 5); root1 = insert(root1, 1); root1 = insert(root1, 10); root1 = insert(root1, 0); root1 = insert(root1, 4); root1 = insert(root1, 7); root1 = insert(root1, 9); // Create second tree as shown in example Node *root2 = NULL; root2 = insert(root2, 10); root2 = insert(root2, 7); root2 = insert(root2, 20); root2 = insert(root2, 4); root2 = insert(root2, 9); cout << "Tree 1 : " ; inorder(root1); cout << endl; cout << "Tree 2 : " ; inorder(root2); cout << "\nCommon Nodes: " ; printCommon(root1, root2); return 0; } |
Java
// Java program of iterative traversal based method to // find common elements in two BSTs. import java.util.*; class GfG { // A BST node static class Node { int key; Node left, right; } // A utility function to create a new node static Node newNode( int ele) { Node temp = new Node(); temp.key = ele; temp.left = null ; temp.right = null ; return temp; } // Function two print common elements in given two trees static void printCommon(Node root1, Node root2) { Stack<Node> s1 = new Stack<Node> (); Stack<Node> s2 = new Stack<Node> (); while ( true ) { // push the Nodes of first tree in stack s1 if (root1 != null ) { s1.push(root1); root1 = root1.left; } // push the Nodes of second tree in stack s2 else if (root2 != null ) { s2.push(root2); root2 = root2.left; } // Both root1 and root2 are NULL here else if (!s1.isEmpty() && !s2.isEmpty()) { root1 = s1.peek(); root2 = s2.peek(); // If current keys in two trees are same if (root1.key == root2.key) { System.out.print(root1.key + " " ); s1.pop(); s2.pop(); // move to the inorder successor root1 = root1.right; root2 = root2.right; } else if (root1.key < root2.key) { // If Node of first tree is smaller, than that of // second tree, then its obvious that the inorder // successors of current Node can have same value // as that of the second tree Node. Thus, we pop // from s2 s1.pop(); root1 = root1.right; // root2 is set to NULL, because we need // new Nodes of tree 1 root2 = null ; } else if (root1.key > root2.key) { s2.pop(); root2 = root2.right; root1 = null ; } } // Both roots and both stacks are empty else break ; } } // A utility function to do inorder traversal static void inorder(Node root) { if (root != null ) { inorder(root.left); System.out.print(root.key + " " ); inorder(root.right); } } /* A utility function to insert a new Node with given key in BST */ static Node insert(Node node, int key) { /* If the tree is empty, return a new Node */ if (node == null ) return newNode(key); /* Otherwise, recur down the tree */ if (key < node.key) node.left = insert(node.left, key); else if (key > node.key) node.right = insert(node.right, key); /* return the (unchanged) Node pointer */ return node; } // Driver program public static void main(String[] args) { // Create first tree as shown in example Node root1 = null ; root1 = insert(root1, 5 ); root1 = insert(root1, 1 ); root1 = insert(root1, 10 ); root1 = insert(root1, 0 ); root1 = insert(root1, 4 ); root1 = insert(root1, 7 ); root1 = insert(root1, 9 ); // Create second tree as shown in example Node root2 = null ; root2 = insert(root2, 10 ); root2 = insert(root2, 7 ); root2 = insert(root2, 20 ); root2 = insert(root2, 4 ); root2 = insert(root2, 9 ); System.out.print( "Tree 1 : " + "\n" ); inorder(root1); System.out.println(); System.out.print( "Tree 2 : " + "\n" ); inorder(root2); System.out.println(); System.out.println( "Common Nodes: " ); printCommon(root1, root2); } } |
Python3
# Python3 program of iterative traversal based # method to find common elements in two BSTs. # A utility function to create a new node class newNode: def __init__( self , key): self .key = key self .left = self .right = None # Function two print common elements # in given two trees def printCommon(root1, root2): # Create two stacks for two inorder # traversals s1 = [] s2 = [] while 1 : # append the Nodes of first # tree in stack s1 if root1: s1.append(root1) root1 = root1.left # append the Nodes of second tree # in stack s2 elif root2: s2.append(root2) root2 = root2.left # Both root1 and root2 are NULL here elif len (s1) ! = 0 and len (s2) ! = 0 : root1 = s1[ - 1 ] root2 = s2[ - 1 ] # If current keys in two trees are same if root1.key = = root2.key: print (root1.key, end = " " ) s1.pop( - 1 ) s2.pop( - 1 ) # move to the inorder successor root1 = root1.right root2 = root2.right elif root1.key < root2.key: # If Node of first tree is smaller, than # that of second tree, then its obvious # that the inorder successors of current # Node can have same value as that of the # second tree Node. Thus, we pop from s2 s1.pop( - 1 ) root1 = root1.right # root2 is set to NULL, because we need # new Nodes of tree 1 root2 = None elif root1.key > root2.key: s2.pop( - 1 ) root2 = root2.right root1 = None # Both roots and both stacks are empty else : break # A utility function to do inorder traversal def inorder(root): if root: inorder(root.left) print (root.key, end = " " ) inorder(root.right) # A utility function to insert a new Node # with given key in BST def insert(node, key): # If the tree is empty, return a new Node if node = = None : return newNode(key) # Otherwise, recur down the tree if key < node.key: node.left = insert(node.left, key) elif key > node.key: node.right = insert(node.right, key) # return the (unchanged) Node pointer return node # Driver Code if __name__ = = '__main__' : # Create first tree as shown in example root1 = None root1 = insert(root1, 5 ) root1 = insert(root1, 1 ) root1 = insert(root1, 10 ) root1 = insert(root1, 0 ) root1 = insert(root1, 4 ) root1 = insert(root1, 7 ) root1 = insert(root1, 9 ) # Create second tree as shown in example root2 = None root2 = insert(root2, 10 ) root2 = insert(root2, 7 ) root2 = insert(root2, 20 ) root2 = insert(root2, 4 ) root2 = insert(root2, 9 ) print ( "Tree 1 : " ) inorder(root1) print () print ( "Tree 2 : " ) inorder(root2) print () print ( "Common Nodes: " ) printCommon(root1, root2) # This code is contributed by PranchalK |
C#
using System; using System.Collections.Generic; // C# program of iterative traversal based method to // find common elements in two BSTs. public class GfG { // A BST node public class Node { public int key; public Node left, right; } // A utility function to create a new node public static Node newNode( int ele) { Node temp = new Node(); temp.key = ele; temp.left = null ; temp.right = null ; return temp; } // Function two print common elements in given two trees public static void printCommon(Node root1, Node root2) { Stack<Node> s1 = new Stack<Node> (); Stack<Node> s2 = new Stack<Node> (); while ( true ) { // push the Nodes of first tree in stack s1 if (root1 != null ) { s1.Push(root1); root1 = root1.left; } // push the Nodes of second tree in stack s2 else if (root2 != null ) { s2.Push(root2); root2 = root2.left; } // Both root1 and root2 are NULL here else if (s1.Count > 0 && s2.Count > 0) { root1 = s1.Peek(); root2 = s2.Peek(); // If current keys in two trees are same if (root1.key == root2.key) { Console.Write(root1.key + " " ); s1.Pop(); s2.Pop(); // move to the inorder successor root1 = root1.right; root2 = root2.right; } else if (root1.key < root2.key) { // If Node of first tree is smaller, than that of // second tree, then its obvious that the inorder // successors of current Node can have same value // as that of the second tree Node. Thus, we pop // from s2 s1.Pop(); root1 = root1.right; // root2 is set to NULL, because we need // new Nodes of tree 1 root2 = null ; } else if (root1.key > root2.key) { s2.Pop(); root2 = root2.right; root1 = null ; } } // Both roots and both stacks are empty else { break ; } } } // A utility function to do inorder traversal public static void inorder(Node root) { if (root != null ) { inorder(root.left); Console.Write(root.key + " " ); inorder(root.right); } } /* A utility function to insert a new Node with given key in BST */ public static Node insert(Node node, int key) { /* If the tree is empty, return a new Node */ if (node == null ) { return newNode(key); } /* Otherwise, recur down the tree */ if (key < node.key) { node.left = insert(node.left, key); } else if (key > node.key) { node.right = insert(node.right, key); } /* return the (unchanged) Node pointer */ return node; } // Driver program public static void Main( string [] args) { // Create first tree as shown in example Node root1 = null ; root1 = insert(root1, 5); root1 = insert(root1, 1); root1 = insert(root1, 10); root1 = insert(root1, 0); root1 = insert(root1, 4); root1 = insert(root1, 7); root1 = insert(root1, 9); // Create second tree as shown in example Node root2 = null ; root2 = insert(root2, 10); root2 = insert(root2, 7); root2 = insert(root2, 20); root2 = insert(root2, 4); root2 = insert(root2, 9); Console.Write( "Tree 1 : " + "\n" ); inorder(root1); Console.WriteLine(); Console.Write( "Tree 2 : " + "\n" ); inorder(root2); Console.WriteLine(); Console.Write( "Common Nodes: " + "\n" ); printCommon(root1, root2); } } // This code is contributed by Shrikant13 |
Output:
4 7 9 10
- Time Complexity: O(n+m).
Here ‘m’ and ‘n’ are number of nodes in first and second tree respectively,as we need to traverse both the trees. - Auxiliary Space :Use of stack for storing values, at-most elements = ‘Height of tree’: O(h1+h2)
This article is contributed by Ekta Goel. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.