题目描述

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

两棵树重复是指它们具有相同的结构以及相同的结点值。


因此,你需要以列表的形式返回上述重复子树的根结点。

来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/find-duplicate-subtrees/

解题思路

判断是否有相同的子树,可以按照指定的规则,把树‘序列化’,如果序列化的树是一致的,那么代表两棵树是一样的。序列化(主要是为了知道自己这颗树是什么样的),本题根据后序遍历进行序列化就可以知道自己是什么样子了,因为知道左右子树,再加上自己根结点,就是当前这棵树的样子。

所以经过后序遍历序列化的字符串作为key,查询map,查询完之后把树放到map中,值增加1,查询结果如果大于1代表树重复了,等于1代表第一次重复,这时需要把当前节点放到数组中作为返回结果。

参考来源:https://labuladong.gitee.io/algo/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%B3%BB%E5%88%97/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%B3%BB%E5%88%973.html

解题代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    private static HashMap<String, Integer> treeMap = new HashMap<>();
    private static List<TreeNode> nodes = new ArrayList<>();

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        //初始化清空数组和map
        nodes.clear();
        treeMap.clear();
        //判断重复的子树
        judgeTree(root);
        return nodes;
    }

    private static String judgeTree(TreeNode root) {
        //如果为空,设置#标识
        if(root == null) {
            return "#";
        }
        
        //递归左子树
        String left = judgeTree(root.left);
        //递归右子树
        String right = judgeTree(root.right);
        //序列化树:方便判断是否有相同的子树
        String tree = left + "," + right + "," + root.val;
        //使用map存储,判断是否重复
        int num = treeMap.getOrDefault(tree, 0);
        //如果为1代表第一次重复,放到数组中返回,起到去重作用
        if(num == 1) {
            nodes.add(root);
        }
        treeMap.put(tree, num+1);
        return tree;
    }
}