老话放在前面根据题意,思考一个二叉树节点须要作什么,到底用什么遍历顺序就清楚了
寻找重复的子树
对于某个节点,如何知道本身是否是重复的
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; }