652. 寻找重复的子树
难度
中等

630

 

 

给你一棵二叉树的根节点 root ,返回所有 重复的子树 。

对于同一类的重复子树,你只需要返回其中任意 一棵 的根结点即可。

如果两棵树具有 相同的结构 和 相同的结点值 ,则认为二者是 重复 的。

 

示例 1:

 

 

 

输入:root = [1,2,3,4,null,2,4,null,null,4]
输出:[[2,4],[4]]
示例 2:

 

 

 

输入:root = [2,1,1]
输出:[[1]]
示例 3:

 

 

 

输入:root = [2,2,2,3,null,3,null]
输出:[[2,3],[3]]
 

提示:

树中的结点数在 [1, 5000] 范围内。
-200 <= Node.val <= 200

 

思路:

根据题意我们需要判断两棵树是否具有相同的结构和节点值?

此时我们思考如何表达数的结构和节点值

我们借助二叉树的序列化,从底部向上序列化二叉树,每序列化一棵子树,借助哈希表

判断是否和已经有的子树重复了,如果没有重复,将其加入到哈希表中,第一次重复,那么我们将该子树序列化的字符串对应的指针改为空,表明存在相同的结构和节点值的该子树,后续如果重复只需要判断该序列化的字符串在哈希表中对应的指针是不是空,如果不是空,那么代表该重复子树对应的字符串已经被加入到了输出结果中,避免同一类型的重复被多次输出.

 

AC代码如下

unordered_map 不排序哈希表

find函数查找是否存在对应键的键值对

复制代码
/**
 * 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:
    unordered_map<string,TreeNode*> recur;
    vector<TreeNode*> res;
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
          //返回所有重复的子树
          //两棵树具有相同的结构和节点值 如何表达树的结构和节点值
          //字符串? 
          //如何判断两棵树相同 到某个节点所遍历到的
          dfs(root);
          return res;
    }

    string dfs(TreeNode* root){
        if(root==nullptr) return "null";
        string s=dfs(root->left)+"l"+to_string(root->val)+dfs(root->right)+"r";
        if(recur.find(s)==recur.end())recur[s]=root;//没有重复的
        else {
           if(recur[s]!=nullptr) res.push_back(root);
           recur[s]=nullptr;
        }
        return s;
    }
};
复制代码