---
# System prepended metadata

title: 652. Find Duplicate Subtrees
tags: [tree, Leetcode, medium, python, c++, hash]

---

###### tags: `Leetcode` `medium` `tree` `hash` `python` `c++`

# 652. Find Duplicate Subtrees

## [題目連結:] https://leetcode.com/problems/find-duplicate-subtrees/

## 題目:
Given the ```root``` of a binary tree, return all **duplicate subtrees**.

For each kind of duplicate subtrees, you only need to return the root node of any **one** of them.

Two trees are **duplicate** if they have the **same structure** with the **same node values**.

![](https://i.imgur.com/4i1HMdL.png)
![](https://i.imgur.com/rCBFJNe.png)
![](https://i.imgur.com/yaEjp2L.png)

## 解題想法:
* 此題為，找出二元樹中所有的重複子樹

* 使用字典紀錄:
    * dictionary:
        * key: path
        * value: 出現次數
    * 對於每顆子樹，將其結構依照**preorder traversal**遍歷保存，存於hash table中
        * ex: 若重複為tree:245 
        * 則res=[[2],[4],[5]] 
        * 因為可以形成分別245、45、5三個tree
        * 使用preorder，才可以保證單一子樹5可以記錄到
    * 當下次再次出現此結構，即可將該root加入到最終結果



## Python:
``` python=
from collections import defaultdict

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
    def insertLeft(self,node):
        if not self.left:
            self.left=TreeNode(node)
        else:
            self.left.insertLeft(node)
    def insertRight(self,node):
        if not self.right:
            self.right=TreeNode(node)
        else:
            self.right.insertRight(node)
    def printTree(self):
        root=self
        stack=[root]
        res=[]
        while stack:
            root=stack.pop(0)
            res.append(root.val)
            if root.left:
                stack.append(root.left)
            if root.right:
                stack.append(root.right)
        print(res)

class Solution(object):
    def findDuplicateSubtrees(self, root):
        """
        :type root: TreeNode
        :rtype: List[TreeNode]
        """
        self.res=[]
        dic=defaultdict(int) #key為path value為出現次數
        self.traversal(root,dic)
        print(dic)
        return self.res
    def traversal(self,root,dic):
        if not root:
            return '#'
        #preorder
        path= str(root.val)+','+self.traversal(root.left,dic)+','+self.traversal(root.right,dic)
        if dic[path]==1: #該path出現過ㄌ
            self.res.append(root)
        dic[path]+=1
        return path

root=TreeNode(1)
root.insertLeft(2)
root.insertRight(3)
root.left.insertLeft(4)
root.left.left.insertLeft(5)
root.right.insertLeft(2)
root.right.insertRight(5)
root.right.left.insertLeft(4)
root.right.left.left.insertLeft(5)
root.printTree()

result=Solution()
ans=result.findDuplicateSubtrees(root)
print(ans)
'''
ex:
            1
        2       3
    4         2     5
5           4
          5

res=[[2],[4],[5]]
'''
```


## C++:
``` cpp=
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        unordered_map<string, int> dic;
        Traversal(root, dic);
        return res;
    }
    string Traversal(TreeNode* root, unordered_map<string, int>& dic){
        if (!root)
            return "#";
        //to_string: Returns a string with the representation of val.
        string path=to_string(root->val)+","+Traversal(root->left, dic)+","+Traversal(root->right, dic);
        if (dic[path]==1)
            res.push_back(root);
        dic[path]+=1;
        return path;
    }

private:
    vector<TreeNode*> res;
};
```