老话放在前面根据题意,思考一个二叉树节点需要做什么,到底用什么遍历顺序就清楚了
寻找重复的子树
对于某个节点,如何知道自己是不是重复的
1.以我为根的这棵二叉树(子树)长啥样?
2.以其他节点为根的子树都长啥样?
我们如何知道自己长啥样呢,可以用后序遍历的框架来解决
void traverse(TreeNode root){
traverse(root.left);
traverse(root.right);
}
这样我们就知道自己长成什么样了
所以,我们可以通过拼接字符串的方式来把二叉树序列化,看下代码
String traverse(TreeNode root){
//对于空节点,可以用一个特殊字符来表示
if(root==null){
return "#";
}
//将左右子树序列化为字符串
String left=traverse(root.left);
String right=traverse(root.right);
//后序遍历位置
//左右子树加上自己,就是以自己为根的二叉树
String subTree=left+","+right+","+root.val;
return subTree;
}
我们用非数字的特殊符#表示空指针,并且用字符,分隔每个二叉树节点值,这属于序列化二叉树的套路。
对于每个节点来说,递归函数中的subTree变量就可以描述以该节点为根的二叉树
接下来,如何知道别人长什么样?
我们可以创建一个外部变量,通过将序列化后的结果保存在其中,那么我们就可以知道别人是不是已经有过了,如果已经存在的话,东哥的代码也解释了一开始使用的是Set结构,那么做完对比的结果就有多个重复的res,所以使用HashMap。
HashMap<String,Integer> memo=new HashMap<>();
LinkedList<TreeNode> res=new LinkedList<>();
List<TreeNode> findDuplicationSubtrees(TreeNode root){
traverse(root);
return res;
}
String traverse(TreeNode root){
if(root==null){
return "#";
}
String left=traverse(root.left);
String right=traverse(root.right);
String subTree=left+","+right+","+root.val;
int freq=meomo.getOrDefault(subTree,0);
if(freq==1){
res.add(root);
}
memo.put(subTree,freq+1);
return subTree;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。