Check if a binary tree is subtree of another binary tree | GeeksforGeeks


Check if a binary tree is subtree of another binary tree | GeeksforGeeks
Given two binary trees, check if the first tree is 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.
Solution: Traverse the tree T in preorder fashion. For every visited node in the traversal, see if the subtree rooted with this node is identical to S.

Time Complexity: Time worst case complexity of above solution is O(mn) where m and n are number of nodes in given two trees.
    static Node root1,root2;
    /* A utility function to check whether trees with roots as root1 and
     root2 are identical or not */
    boolean areIdentical(Node node1, Node node2) {
        /* base cases */
        if (node1 == null && node2 == null) {
            return true;
        }
        if (node1 == null || node2 == null) {
            return false;
        }
        /* Check if the data of both roots is same and data of left and right
         subtrees are also same */
        return (node1.data == node2.data
                && areIdentical(node1.left, node2.left)
                && areIdentical(node1.right, node2.right));
    }
    /* 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;
        }
        /* Check the tree with root as current node */
        if (areIdentical(T, S)) {
            return true;
        }
        /* If the tree with root as current node doesn't match then
         try left and right subtrees one by one */
        return isSubtree(T.left, S)
                || isSubtree(T.right, S);
    }
http://www.geeksforgeeks.org/check-binary-tree-subtree-another-binary-tree-set-2/
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.

1) Find inorder and preorder traversals of T, store them in two auxiliary arrays inT[] and preT[].
2) Find inorder and preorder traversals of S, 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.

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

The above algorithm can be extended to handle such cases by adding a special character whenever we encounter NULL in inorder and preorder traversals.

Time Complexity: Inorder and Preorder traversals of Binary Tree take O(n) time. The functionstrstr() can also be implemented in O(n) time using KMP string matching algorithm. 
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.

Inorder and Preorder traversals of small tree or Tree1 are

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.
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);
    }

http://www.jiuzhang.com/solutions/subtree/
    public boolean isSubtree(TreeNode T1, TreeNode T2) {
        if (T2 == null) {
            return true;
        }
        if (T1 == null) {
            return false;
        }
        
        if (isEqual(T1, T2)) {
            return true;
        }
        if (isSubtree(T1.left, T2) || isSubtree(T1.right, T2)) {
            return true;
        }
        return false;
    }
    
    private boolean isEqual(TreeNode T1, TreeNode T2) {
        if (T1 == null || T2 == null) {
            return T1 == T2;
        }
        if (T1.val != T2.val) {
            return false;
        }
        return isEqual(T1.left, T2.left) && isEqual(T1.right, T2.right);
    }
http://lintcode.peqiu.com/content/lintcode/subtree.html
首先是特殊情况的处理,然后是树的遍历,可以用栈或者递归,对于判断两个树是否相等,用递归的方式,用栈的话需要同时入出栈,比较麻烦
    bool isSubtree(TreeNode *T1, TreeNode *T2) {
        // write your code here
        if (!T2) {
            return true;
        } else if (!T1) {  // !T1 && T2
            return false;
        }
        stack tmp;
        tmp.push(T1);
        while(!tmp.empty()) {
            TreeNode* pNode = tmp.top();
            if(isSubtreeHelper(pNode, T2))
                return true;
            tmp.pop();
            if(pNode->right)
                tmp.push(pNode->right);
            if(pNode->left)
                tmp.push(pNode->left);
        }
        return false;
    }
    bool isSubtreeHelper(TreeNode *T1, TreeNode *T2) {
        if (!T1 && !T2) {
            return true;
        }
        if (T1 && T2) {
            return T1->val == T2->val &&
                   isSubtreeHelper(T1->left, T2->left) &&
                   isSubtreeHelper(T1->right, T2->right);
        }

        return false;
    }
http://algorithms.tutorialhorizon.com/given-two-binary-trees-check-if-one-binary-tree-is-a-subtree-of-another/
Should use LinkedList<String> or StringBuilder.
public String inOrder(Node root, String i){
if(root!=null){
return inOrder(root.left,i) + "  " + root.data + "  " +inOrder(root.right,i);
}
return "";
}
public String postOrder(Node root, String i){
if(root!=null){
return  postOrder(root.left,i) + "  " + postOrder(root.right,i) + "  " + root.data;
}
return "";
}
public boolean checkSubtree(Node rootA, Node rootB){
String inOrderA = inOrder(rootA,"");
String inOrderB = inOrder(rootB,"");
String postOrderA = postOrder(rootA,"");
String postOrderB = postOrder(rootB,"");
return (inOrderA.toLowerCase().contains(inOrderB.toLowerCase()) && postOrderA.toLowerCase().contains(postOrderB.toLowerCase()));
}
http://www.codebytes.in/2015/01/checking-if-given-binary-tree-is-sub.html ===>not good solution
1. Traverse T1, find nodes that match the root of T2.
2. For all the nodes that match, check if the trees with those roots are equivalent.
    private void getIdenticals(Node node, Node B, List<Node> store){
        if(node==null) return;
        if(node.equals(B)) store.add(node);
        getIdenticals(node.left, B, store);
        getIdenticals(node.right, B, store); 
    }
    
    public boolean isSubtree(Node root, Node B){ 
        if(root == null || B == null)return false;
        List<Node> possibleNodes = new ArrayList<>();
        getIdenticals(root, B, possibleNodes);
        for(Node n:possibleNodes)
            if(match(n, B))return true;
        return false;
    }
    
    private boolean match(Node head, Node B){
        if(head==null && B == null)return true;
        if(head==null || B == null)return false;
        if(head.equals(B)){
            if(match(head.left, B.left) && match(head.right, B.right)) return true;
        }
        return false;
    }

Tl and T2 are two very large binary trees, with Tl much bigger than T2. Create an
algorithm to determine ifT2 is a subtree of Tl.
A tree T2 is a subtree of Tl if there exists a node n in Tl such that the subtree of n is identical to T2.
That is, if you cut off the tree at node n, the two trees would be identical.


This approach takes O(n + m) time and O(n + m) space,
boolean containsTree(TreeNode tl, TreeNode t2) {
        StringBuilder stringl =  new StringBuilder();
        StringBuilder string2 = new StringBuilder();

        getOrderString(tl, s tringl);
        getOrderString(t2, string2);

        return stringl.indexOf(string2.toString()) != -1;
}

void getOrderString(TreeNode node, StringBuilder sb) {
        if (node == null) {
                sb.append ( "X"); / / Add null indicator
                return;
        }
        sb.append (node.data + " "); / / Add root
        getOrderString(node.left, sb); // Add left
        getOrderString(node.right, sb); // Add right
}

An alternative approach is to search through the larger tree, Tl. Each time a node in Tl matches the root
ofT2, call match Tree. The match Tree method will compare the two subtrees to see if they are identical.

boolean containsTree(TreeNode tl, TreeNode t2) {
        if (t2 == null) return true; // The empty tree is always a subtree
        return subTree(tl, t2);
}

boolean subTree(TreeNode rl, TreeNode r2) {
        if (rl == null) {
                return false; // big tree empty & subtree still not found.
        } else if (rl.data == r2.data && matchTree(rl, r2)) {
                return true;
        }
        return subTree(rl.left, r2) || subTree(rl.right, r2);
}

boolean matchTree(TreeNode rl, TreeNode r2) {
        if (rl == null && r2 == null) {
                return true; // nothing left in the subtree
        } else if (rl == null || r2 == null) {
                return false; // exactly tree is empty, therefore trees dones't match
        } else if (rl.data != r2.data) {
                return false; // data doesn't match
        } else {
                return matchTree(rl.left, r2.left) && matchTree(rl.right, r2.right);
        }
}

https://reeestart.wordpress.com/2016/06/14/google-is-subtree/
不算难的一道题,一看就是递归。但是注意分析这道题的时间复杂度,不是O(n)喔。如果是递归的做法,应该是O(n^2)。而且也有两种递归方式,一种直接递归找subtree,另一种借助isSame()


[Solution #2]
当然这题也有O(n)的解法,对两个tree的任意两种order traversal做KMP. 不包括level order!!
// O(n^2) time 直接递归
class Solution {
  public boolean isSubtree(TreeNode s, TreeNode t) {
    if (s == null) {
      return true;
    }
    if (t == null) {
      return false;
    }
 
    return dfs(s, t);
  }
 
  private boolean dfs(TreeNode s, TreeNode t) {
    if (s == null && t == null) {
      return true;
    }
    if (s == null || t == null) {
      return false;
    }
 
    boolean result = false;
    if (s.val == t.val) {
      result |= dfs(s.left, t.left) && dfs(s.right, t.right);
    }
    result |= dfs(s, t.left);
    result |= dfs(s, t.right);
    return result;
  }
}
 
// O(n^2) time 借助isSame() 来递归
class Solution2 {
  public boolean isSubtree(TreeNode s, TreeNode t) {
    if (s == null) {
      return true;
    }
    if (t == null) {
      return false;
    }
     
    if (isSame(s, t)) {
      return true;
    }
     
    return isSubtree(s, t.left) || isSubtree(s, t.right);
  }
   
  private boolean isSame(TreeNode s, TreeNode t) {
    if (s == null && t == null) {
      return true;
    }
    if (s == null || t == null) {
      return false;
    }
    if (s.val != t.val) {
      return false;
    }
     
    return isSame(s.left, t.left) && isSame(s.right, t.right);
  }
}
https://discuss.leetcode.com/topic/18/check-if-a-binary-tree-is-a-subtree-of-another-binary-tree/11
Read full article from Check if a binary tree is subtree of another binary tree | GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts