题目描述
给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。
两棵树重复是指它们具有相同的结构以及相同的结点值。
因此,你需要以列表的形式返回上述重复子树的根结点。
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/find-duplicate-subtrees/
解题思路
判断是否有相同的子树,可以按照指定的规则,把树‘序列化’,如果序列化的树是一致的,那么代表两棵树是一样的。序列化(主要是为了知道自己这颗树是什么样的),本题根据后序遍历进行序列化就可以知道自己是什么样子了,因为知道左右子树,再加上自己根结点,就是当前这棵树的样子。
所以经过后序遍历序列化的字符串作为key,查询map,查询完之后把树放到map中,值增加1,查询结果如果大于1代表树重复了,等于1代表第一次重复,这时需要把当前节点放到数组中作为返回结果。
解题代码
/**
* 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;
}
}