Print Common Nodes in Two Binary Search Trees

05 Aug, 2021
Given two Binary Search Trees, find common nodes in them. In other words, find intersection of two BSTs.
Example:
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).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.
Method 3 (Linear Time and limited Extra Space)The idea is to use iterative inorder traversal
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

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

C++
Java
Python3
C#
// C++ program of iterative traversal based method to// find common elements in two BSTs.#include<iostream>#include<stack>using namespace std;  // A BST nodestruct Node{    int key;    struct Node *left, *right;};  // A utility function to create a new nodeNode *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 treesvoid 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 traversalvoid 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 programint 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 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 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
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
4 7 9 10
Complexity Analysis: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)
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.
prerna saini
shrikanth13
PranchalKatiyar
Suvo
bidibaaz123
sagar0719kumar
sumitgumber28
Amazon
Binary Search Tree
Tree
Amazon
Binary Search Tree
Tree
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.