📜  检查二叉树是否包含大小为 2 或更大的重复子树

📅  最后修改于: 2022-05-13 01:57:19.953000             🧑  作者: Mango

检查二叉树是否包含大小为 2 或更大的重复子树

给定一个二叉树,检查二叉树是否包含大小为 2 或更大的重复子树。
注意:两个相同的叶节点不被视为叶节点的子树大小为一。

Input :  Binary Tree 
               A
             /    \ 
           B        C
         /   \       \    
        D     E       B     
                     /  \    
                    D    E
Output : Yes

提问:谷歌面试

树

具有重复子树的树 [蓝色椭圆突出显示]

[方法一]
一个简单的解决方案是,我们选择树的每个节点并尝试查找给定树的任何子树是否存在于与该子树相同的树中。在这里,我们可以使用下面的帖子来查找子树是否存在于树中的其他任何地方。
检查一棵二叉树是否是另一棵二叉树的子树

【方法二】(高效解决方案)
基于树序列化和散列的高效解决方案。这个想法是将子树序列化为字符串并将字符串存储在哈希表中。一旦我们发现哈希表中已经存在一个序列化的树(不是叶子),我们就返回 true。

下面是上述想法的实现。

C++
// C++ program to find if there is a duplicate
// sub-tree of size 2 or more.
#include
using namespace std;
 
// Separator node
const char MARKER = '$';
 
// Structure for a binary tree node
struct Node
{
    char key;
    Node *left, *right;
};
 
// A utility function to create a new node
Node* newNode(char key)
{
    Node* node = new Node;
    node->key = key;
    node->left = node->right = NULL;
    return node;
}
 
unordered_set subtrees;
 
// This function returns empty string if tree
// contains a duplicate subtree of size 2 or more.
string dupSubUtil(Node *root)
{
    string s = "";
 
    // If current node is NULL, return marker
    if (root == NULL)
        return s + MARKER;
 
    // If left subtree has a duplicate subtree.
    string lStr = dupSubUtil(root->left);
    if (lStr.compare(s) == 0)
    return s;
 
    // Do same for right subtree
    string rStr = dupSubUtil(root->right);
    if (rStr.compare(s) == 0)
    return s;
 
    // Serialize current subtree
    s = s + root->key + lStr + rStr;
 
    // If current subtree already exists in hash
    // table. [Note that size of a serialized tree
    // with single node is 3 as it has two marker
    // nodes.
    if (s.length() > 3 &&
        subtrees.find(s) != subtrees.end())
    return "";
 
    subtrees.insert(s);
 
    return s;
}
 
// Driver program to test above functions
int main()
{
    Node *root = newNode('A');
    root->left = newNode('B');
    root->right = newNode('C');
    root->left->left = newNode('D');
    root->left->right = newNode('E');
    root->right->right = newNode('B');
    root->right->right->right = newNode('E');
    root->right->right->left= newNode('D');
 
    string str = dupSubUtil(root);
 
    (str.compare("") == 0) ? cout << " Yes ":
                            cout << " No " ;
    return 0;
}


Java
// Java program to find if there is a duplicate
// sub-tree of size 2 or more.
import java.util.HashSet;
public class Main {
 
    static char MARKER = '$';
 
    // This function returns empty string if tree
    // contains a duplicate subtree of size 2 or more.
    public static String dupSubUtil(Node root, HashSet subtrees)
    {
        String s = "";
     
        // If current node is NULL, return marker
        if (root == null)
            return s + MARKER;
     
        // If left subtree has a duplicate subtree.
        String lStr = dupSubUtil(root.left,subtrees);
        if (lStr.equals(s))
            return s;
     
        // Do same for right subtree
        String rStr = dupSubUtil(root.right,subtrees);
        if (rStr.equals(s))
            return s;
     
        // Serialize current subtree
        s = s + root.data + lStr + rStr;
     
        // If current subtree already exists in hash
        // table. [Note that size of a serialized tree
        // with single node is 3 as it has two marker
        // nodes.
        if (s.length() > 3 && subtrees.contains(s))
            return "";
     
        subtrees.add(s);
        return s;
    }
 
    //Function to find if the Binary Tree contains duplicate
    //subtrees of size 2 or more
    public static String dupSub(Node root)
    {
        HashSet subtrees=new HashSet<>();
        return dupSubUtil(root,subtrees);
    }
 
    public static void main(String args[])
    {
        Node root = new Node('A');
        root.left = new Node('B');
        root.right = new Node('C');
        root.left.left = new Node('D');
        root.left.right = new Node('E');
        root.right.right = new Node('B');
        root.right.right.right = new Node('E');
        root.right.right.left= new Node('D');
        String str = dupSub(root);
        if(str.equals(""))
            System.out.print(" Yes ");
        else   
            System.out.print(" No ");
    }
}
 
// A binary tree Node has data,
// pointer to left child
// and a pointer to right child
class Node {
    int data;
    Node left,right;
    Node(int data)
    {
        this.data=data;
    }
};
//This code is contributed by Gaurav Tiwari


Python3
# Python3 program to find if there is
# a duplicate sub-tree of size 2 or more
 
# Separator node
MARKER = '$'
 
# Structure for a binary tree node
class Node:
     
    def __init__(self, x):
         
        self.key = x
        self.left = None
        self.right = None
 
subtrees = {}
 
# This function returns empty if tree
# contains a duplicate subtree of size
# 2 or more.
def dupSubUtil(root):
     
    global subtrees
 
    s = ""
 
    # If current node is None, return marker
    if (root == None):
        return s + MARKER
 
    # If left subtree has a duplicate subtree.
    lStr = dupSubUtil(root.left)
     
    if (s in lStr):
       return s
 
    # Do same for right subtree
    rStr = dupSubUtil(root.right)
     
    if (s in rStr):
       return s
 
    # Serialize current subtree
    s = s + root.key + lStr + rStr
 
    # If current subtree already exists in hash
    # table. [Note that size of a serialized tree
    # with single node is 3 as it has two marker
    # nodes.
    if (len(s) > 3 and s in subtrees):
       return ""
 
    subtrees[s] = 1
 
    return s
 
# Driver code
if __name__ == '__main__':
     
    root = Node('A')
    root.left = Node('B')
    root.right = Node('C')
    root.left.left = Node('D')
    root.left.right = Node('E')
    root.right.right = Node('B')
    root.right.right.right = Node('E')
    root.right.right.left= Node('D')
 
    str = dupSubUtil(root)
 
    if "" in str:
        print(" Yes ")
    else:
        print(" No ")
 
# This code is contributed by mohit kumar 29


C#
// C# program to find if there is a duplicate
// sub-tree of size 2 or more.
using System;
using System.Collections.Generic;
 
class GFG
{
 
    static char MARKER = '$';
 
    // This function returns empty string if tree
    // contains a duplicate subtree of size 2 or more.
    public static String dupSubUtil(Node root,
                    HashSet subtrees)
    {
        String s = "";
     
        // If current node is NULL, return marker
        if (root == null)
            return s + MARKER;
     
        // If left subtree has a duplicate subtree.
        String lStr = dupSubUtil(root.left,subtrees);
        if (lStr.Equals(s))
            return s;
     
        // Do same for right subtree
        String rStr = dupSubUtil(root.right,subtrees);
        if (rStr.Equals(s))
            return s;
     
        // Serialize current subtree
        s = s + root.data + lStr + rStr;
     
        // If current subtree already exists in hash
        // table. [Note that size of a serialized tree
        // with single node is 3 as it has two marker
        // nodes.
        if (s.Length > 3 && subtrees.Contains(s))
            return "";
     
        subtrees.Add(s);
        return s;
    }
 
    // Function to find if the Binary Tree contains
    // duplicate subtrees of size 2 or more
    public static String dupSub(Node root)
    {
        HashSet subtrees = new HashSet();
        return dupSubUtil(root,subtrees);
    }
 
    // Driver code
    public static void Main(String []args)
    {
        Node root = new Node('A');
        root.left = new Node('B');
        root.right = new Node('C');
        root.left.left = new Node('D');
        root.left.right = new Node('E');
        root.right.right = new Node('B');
        root.right.right.right = new Node('E');
        root.right.right.left= new Node('D');
        String str = dupSub(root);
        if(str.Equals(""))
            Console.Write(" Yes ");
        else
            Console.Write(" No ");
    }
}
 
// A binary tree Node has data,
// pointer to left child
// and a pointer to right child
public class Node
{
    public int data;
    public Node left,right;
    public Node(int data)
    {
        this.data = data;
    }
};
 
// This code is contributed by 29AjayKumar


Javascript


输出:

Yes