Skip to content
Related Articles
Open in App
Not now

Related Articles

Check if a binary tree is subtree of another binary tree | Set 2

Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 23 Jun, 2022
Improve Article
Save Article

Given two binary trees, check if the first tree is a subtree of the second one. A subtree of a tree T is a tree S consisting of a node in T and all of its descendants in T. 
The subtree corresponding to the root node is the entire tree; the subtree corresponding to any other node is called a proper subtree.
For example, in the following case, Tree1 is a subtree of Tree2. 

        Tree1
          x 
        /    \
      a       b
       \
        c


        Tree2
              z
            /   \
          x      e
        /    \     \
      a       b      k
       \
        c

 

We have discussed an O(n2) solution for this problem. In this post, the O(n) solution is discussed. The idea is based on the fact that inorder and preorder/postorder uniquely identify a binary tree. Tree S is a subtree of T if both inorder and preorder traversals of S are substrings of inorder and preorder traversals of T respectively.
Following are detailed steps.
1) Find inorder and preorder traversals of T, and store them in two auxiliary arrays inT[] and preT[].
2) Find inorder and preorder traversals of S, and store them in two auxiliary arrays inS[] and preS[].
3) If inS[] is a subarray of inT[] and preS[] is a subarray preT[], then S is a subtree of T. Else not.
We can also use postorder traversal in place of preorder in the above algorithm.
Let us consider the above example 

Inorder and Preorder traversals of the big tree are.
inT[]   =  {a, c, x, b, z, e, k}
preT[]  =  {z, x, a, c, b, e, k}

Inorder and Preorder traversals of small tree are
inS[]  = {a, c, x, b}
preS[] = {x, a, c, b}

We can easily figure out that inS[] is a subarray of
inT[] and preS[] is a subarray of preT[]. 

EDIT

The above algorithm doesn't work for cases where a tree is present
in another tree, but not as a subtree. Consider the following example.

        Tree1
          x 
        /    \
      a       b
     /        
    c         


        Tree2
          x 
        /    \
      a       b
     /         \
    c            d

Inorder and Preorder traversals of the big tree or Tree2 are.
inT[]   =  {c, a, x, b, d}
preT[]  =  {x, a, c, b, d}

Inorder and Preorder traversals of small tree or Tree1 are-
inS[]  = {c, a, x, b}
preS[] = {x, a, c, b}

The Tree2 is not a subtree of Tree1, but inS[] and preS[] are
subarrays of inT[] and preT[] respectively.

The above algorithm can be extended to handle such cases by adding a special character whenever we encounter NULL in inorder and preorder traversals. Thanks to Shivam Goel for suggesting this extension. 
Following is the implementation of the above algorithm.
 

C++




#include <cstring>
#include <iostream>
using namespace std;
#define MAX 100
 
// Structure of a tree node
struct Node {
    char key;
    struct Node *left, *right;
};
 
// A utility function to create a new BST node
Node* newNode(char item)
{
    Node* temp = new Node;
    temp->key = item;
    temp->left = temp->right = NULL;
    return temp;
}
 
// A utility function to store inorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
void storeInorder(Node* root, char arr[], int& i)
{
    if (root == NULL) {
        arr[i++] = '$';
        return;
    }
    storeInorder(root->left, arr, i);
    arr[i++] = root->key;
    storeInorder(root->right, arr, i);
}
 
// A utility function to store preorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
void storePreOrder(Node* root, char arr[], int& i)
{
    if (root == NULL) {
        arr[i++] = '$';
        return;
    }
    arr[i++] = root->key;
    storePreOrder(root->left, arr, i);
    storePreOrder(root->right, arr, i);
}
 
/* This function returns true if S is a subtree of T, otherwise false */
bool isSubtree(Node* T, Node* S)
{
    /* base cases */
    if (S == NULL)
        return true;
    if (T == NULL)
        return false;
 
    // Store Inorder traversals of T and S in inT[0..m-1]
    // and inS[0..n-1] respectively
    int m = 0, n = 0;
    char inT[MAX], inS[MAX];
    storeInorder(T, inT, m);
    storeInorder(S, inS, n);
    inT[m] = '\0', inS[n] = '\0';
 
    // If inS[] is not a substring of inT[], return false
    if (strstr(inT, inS) == NULL)
        return false;
 
    // Store Preorder traversals of T and S in preT[0..m-1]
    // and preS[0..n-1] respectively
    m = 0, n = 0;
    char preT[MAX], preS[MAX];
    storePreOrder(T, preT, m);
    storePreOrder(S, preS, n);
    preT[m] = '\0', preS[n] = '\0';
 
    // If preS[] is not a substring of preT[], return false
    // Else return true
    return (strstr(preT, preS) != NULL);
}
 
// Driver program to test above function
int main()
{
    Node* T = newNode('a');
    T->left = newNode('b');
    T->right = newNode('d');
    T->left->left = newNode('c');
    T->right->right = newNode('e');
 
    Node* S = newNode('a');
    S->left = newNode('b');
    S->left->left = newNode('c');
    S->right = newNode('d');
 
    if (isSubtree(T, S))
        cout << "Yes: S is a subtree of T";
    else
        cout << "No: S is NOT a subtree of T";
 
    return 0;
}


Java




// Java program to check if binary tree
// is subtree of another binary tree
class Node {
 
    char data;
    Node left, right;
 
    Node(char item)
    {
        data = item;
        left = right = null;
    }
}
 
class Passing {
 
    int i;
    int m = 0;
    int n = 0;
}
 
class BinaryTree {
 
    static Node root;
    Passing p = new Passing();
 
    String strstr(String haystack, String needle)
    {
        if (haystack == null || needle == null) {
            return null;
        }
        int hLength = haystack.length();
        int nLength = needle.length();
        if (hLength < nLength) {
            return null;
        }
        if (nLength == 0) {
            return haystack;
        }
        for (int i = 0; i <= hLength - nLength; i++) {
            if (haystack.charAt(i) == needle.charAt(0)) {
                int j = 0;
                for (; j < nLength; j++) {
                    if (haystack.charAt(i + j) != needle.charAt(j)) {
                        break;
                    }
                }
                if (j == nLength) {
                    return haystack.substring(i);
                }
            }
        }
        return null;
    }
 
    // A utility function to store inorder traversal of tree rooted
    // with root in an array arr[]. Note that i is passed as reference
    void storeInorder(Node node, char arr[], Passing i)
    {
        if (node == null) {
            arr[i.i++] = '$';
            return;
        }
        storeInorder(node.left, arr, i);
        arr[i.i++] = node.data;
        storeInorder(node.right, arr, i);
    }
 
    // A utility function to store preorder traversal of tree rooted
    // with root in an array arr[]. Note that i is passed as reference
    void storePreOrder(Node node, char arr[], Passing i)
    {
        if (node == null) {
            arr[i.i++] = '$';
            return;
        }
        arr[i.i++] = node.data;
        storePreOrder(node.left, arr, i);
        storePreOrder(node.right, arr, i);
    }
 
    /* This function returns true if S is a subtree of T, otherwise false */
    boolean isSubtree(Node T, Node S)
    {
        /* base cases */
        if (S == null) {
            return true;
        }
        if (T == null) {
            return false;
        }
 
        // Store Inorder traversals of T and S in inT[0..m-1]
        // and inS[0..n-1] respectively
        char inT[] = new char[100];
        String op1 = String.valueOf(inT);
        char inS[] = new char[100];
        String op2 = String.valueOf(inS);
        storeInorder(T, inT, p);
        storeInorder(S, inS, p);
        inT[p.m] = '\0';
        inS[p.m] = '\0';
 
        // If inS[] is not a substring of preS[], return false
        if (strstr(op1, op2) == null) {
            return false;
        }
 
        // Store Preorder traversals of T and S in inT[0..m-1]
        // and inS[0..n-1] respectively
        p.m = 0;
        p.n = 0;
        char preT[] = new char[100];
        char preS[] = new char[100];
        String op3 = String.valueOf(preT);
        String op4 = String.valueOf(preS);
        storePreOrder(T, preT, p);
        storePreOrder(S, preS, p);
        preT[p.m] = '\0';
        preS[p.n] = '\0';
 
        // If inS[] is not a substring of preS[], return false
        // Else return true
        return (strstr(op3, op4) != null);
    }
 
    // Driver program to test above functions
    public static void main(String args[])
    {
        BinaryTree tree = new BinaryTree();
        Node T = new Node('a');
        T.left = new Node('b');
        T.right = new Node('d');
        T.left.left = new Node('c');
        T.right.right = new Node('e');
 
        Node S = new Node('a');
        S.left = new Node('b');
        S.right = new Node('d');
        S.left.left = new Node('c');
 
        if (tree.isSubtree(T, S)) {
            System.out.println("Yes, S is a subtree of T");
        }
        else {
            System.out.println("No, S is not a subtree of T");
        }
    }
}
 
// This code is contributed by Mayank Jaiswal


Python3




MAX = 100
 
# class for a tree node
class Node:
    def __init__(self):
        self.key = ' '
        self.left = None
        self.right = None
 
# A utility function to create a new BST node
def newNode(item):
    temp = Node()
    temp.key = item
    return temp
 
# A utility function to store inorder traversal of tree rooted
# with root in an array arr[]. Note that i is passed as reference
def storeInorder(root, i):
    if (root == None):
        return '$'
    res = storeInorder(root.left, i)
    res += root.key
    res += storeInorder(root.right, i)
    return res
 
# A utility function to store preorder traversal of tree rooted
# with root in an array arr[]. Note that i is passed as reference
def storePreOrder(root, i):
    if (root == None):
        return '$'
    res = root.key
    res += storePreOrder(root.left, i)
    res += storePreOrder(root.right, i)
    return res
 
# This function returns true if S is a subtree of T, otherwise false
def isSubtree(T, S):
    # base cases
    if (S == None):
        return True
    if (T == None):
        return False
 
    # Store Inorder traversals of T and S in inT[0..m-1]
    # and inS[0..n-1] respectively
    m = 0
    n = 0
    inT = storeInorder(T, m)
    inS = storeInorder(S, n)
 
    # If inS[] is not a substring of inT[], return false
    res = True
    if inS in inT:
        res = True
    else:
        res = False
    if(res == False):
        return res
 
    # Store Preorder traversals of T and S in preT[0..m-1]
    # and preS[0..n-1] respectively
    m = 0
    n = 0
    preT = storePreOrder(T, m)
    preS = storePreOrder(S, n)
 
    # If preS[] is not a substring of preT[], return false
    # Else return true
    if preS in preT:
        return True
    else:
        return False
 
# Driver program to test above function
T = newNode('a')
T.left = newNode('b')
T.right = newNode('d')
T.left.left = newNode('c')
T.right.right = newNode('e')
 
S = newNode('a')
S.left = newNode('b')
S.left.left = newNode('c')
S.right = newNode('d')
 
if (isSubtree(T, S)):
    print("Yes: S is a subtree of T")
else:
    print("No: S is NOT a subtree of T")
 
    # This code is contributed by rj13to.


C#




// C# program to check if binary tree is
// subtree of another binary tree
using System;
 
public class Node {
 
    public char data;
    public Node left, right;
 
    public Node(char item)
    {
        data = item;
        left = right = null;
    }
}
 
public class Passing {
 
    public int i;
    public int m = 0;
    public int n = 0;
}
 
public class BinaryTree {
 
    static Node root;
    Passing p = new Passing();
 
    String strstr(String haystack, String needle)
    {
        if (haystack == null || needle == null) {
            return null;
        }
        int hLength = haystack.Length;
        int nLength = needle.Length;
        if (hLength < nLength) {
            return null;
        }
        if (nLength == 0) {
            return haystack;
        }
        for (int i = 0; i <= hLength - nLength; i++) {
            if (haystack[i] == needle[0]) {
                int j = 0;
                for (; j < nLength; j++) {
                    if (haystack[i + j] != needle[j]) {
                        break;
                    }
                }
                if (j == nLength) {
                    return haystack.Substring(i);
                }
            }
        }
        return null;
    }
 
    // A utility function to store inorder
    // traversal of tree rooted with root in
    // an array arr[]. Note that i is passed as reference
    void storeInorder(Node node, char[] arr, Passing i)
    {
        if (node == null) {
            arr[i.i++] = '$';
            return;
        }
        storeInorder(node.left, arr, i);
        arr[i.i++] = node.data;
        storeInorder(node.right, arr, i);
    }
 
    // A utility function to store preorder
    // traversal of tree rooted with root in
    // an array arr[]. Note that i is passed as reference
    void storePreOrder(Node node, char[] arr, Passing i)
    {
        if (node == null) {
            arr[i.i++] = '$';
            return;
        }
        arr[i.i++] = node.data;
        storePreOrder(node.left, arr, i);
        storePreOrder(node.right, arr, i);
    }
 
    /* This function returns true if S
    is a subtree of T, otherwise false */
    bool isSubtree(Node T, Node S)
    {
        /* base cases */
        if (S == null) {
            return true;
        }
        if (T == null) {
            return false;
        }
 
        // Store Inorder traversals of T and S in inT[0..m-1]
        // and inS[0..n-1] respectively
        char[] inT = new char[100];
        String op1 = String.Join("", inT);
        char[] inS = new char[100];
        String op2 = String.Join("", inS);
        storeInorder(T, inT, p);
        storeInorder(S, inS, p);
        inT[p.m] = '\0';
        inS[p.m] = '\0';
 
        // If inS[] is not a substring of preS[], return false
        if (strstr(op1, op2) != null) {
            return false;
        }
 
        // Store Preorder traversals of T and S in inT[0..m-1]
        // and inS[0..n-1] respectively
        p.m = 0;
        p.n = 0;
        char[] preT = new char[100];
        char[] preS = new char[100];
        String op3 = String.Join("", preT);
        String op4 = String.Join("", preS);
        storePreOrder(T, preT, p);
        storePreOrder(S, preS, p);
        preT[p.m] = '\0';
        preS[p.n] = '\0';
 
        // If inS[] is not a substring of preS[], return false
        // Else return true
        return (strstr(op3, op4) != null);
    }
 
    // Driver program to test above functions
    public static void Main(String[] args)
    {
        BinaryTree tree = new BinaryTree();
        Node T = new Node('a');
        T.left = new Node('b');
        T.right = new Node('d');
        T.left.left = new Node('c');
        T.right.right = new Node('e');
 
        Node S = new Node('a');
        S.left = new Node('b');
        S.right = new Node('d');
        S.left.left = new Node('c');
 
        if (tree.isSubtree(T, S)) {
            Console.WriteLine("Yes, S is a subtree of T");
        }
        else {
            Console.WriteLine("No, S is not a subtree of T");
        }
    }
}
 
// This code contributed by Rajput-Ji


Javascript




<script>
 
const MAX = 100
 
// class for a tree node
class Node{
    constructor(){
        this.key = ' '
        this.left = null
        this.right = null
    }
}
 
// A utility function to create a new BST node
function newNode(item){
    temp = new Node()
    temp.key = item
    return temp
}
 
// A utility function to store inorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
function storeInorder(root, i){
    if (root == null)
        return '$'
    res = storeInorder(root.left, i)
    res += root.key
    res += storeInorder(root.right, i)
    return res
}
 
// A utility function to store preorder traversal of tree rooted
// with root in an array arr[]. Note that i is passed as reference
function storePreOrder(root, i){
    if (root == null)
        return '$'
    res = root.key
    res += storePreOrder(root.left, i)
    res += storePreOrder(root.right, i)
    return res
}
 
// This function returns true if S is a subtree of T, otherwise false
function isSubtree(T, S){
    // base cases
    if (S == null)
        return true
    if (T == null)
        return false
 
    // Store Inorder traversals of T and S in inT[0..m-1]
    // and inS[0..n-1] respectively
    let m = 0
    let n = 0
    let inT = storeInorder(T, m)
    let inS = storeInorder(S, n)
 
    // If inS[] is not a substring of inT[], return false
    res = true
    if(inT.indexOf(inT) !== -1)
        res = true
    else
        res = false
    if(res == false)
        return res
 
    // Store Preorder traversals of T and S in preT[0..m-1]
    // and preS[0..n-1] respectively
    m = 0
    n = 0
    let preT = storePreOrder(T, m)
    let preS = storePreOrder(S, n)
 
    // If preS[] is not a substring of preT[], return false
    // Else return true
    if(preT.indexOf(preS) !== -1)
        return true
    else
        return false
}
 
// Driver program to test above function
 
let T = new newNode('a')
T.left = new newNode('b')
T.right = new newNode('d')
T.left.left = new newNode('c')
T.right.right = new newNode('e')
 
let S = new newNode('a')
S.left = new newNode('b')
S.left.left = new newNode('c')
S.right = new newNode('d')
 
if (isSubtree(T, S))
    document.write("Yes: S is a subtree of T","</br>")
else
    document.write("No: S is NOT a subtree of T","</br>")
 
// This code is contributed by shinjanpatra
 
</script>


Output: 

No: S is NOT a subtree of T

Time Complexity: Inorder and Preorder traversals of Binary Tree take O(n) time. The function strstr() can also be implemented in O(n) time using the KMP string matching algorithm.
Auxiliary Space: O(n)
Thanks to Ashwini Singh for suggesting this method. Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above
 


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!