leetcode652 - Find Duplicate Subtrees - medium
Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only need to return the root node of any oneof them.
Two trees are duplicate if they have the same structure with same node values.
Example 1:
1
/ \
2 3
/ / \
4 2 4
/
4
The following are two duplicate subtrees:
2
/
4 and 4
Therefore, you need to return above trees' root in the form of a list.
树的DFS。后序遍历。树的serialization。
思路:要区分不同的subtrees,就规定一种序列化方法,序列化之后两者得到的答案一样就说明结构与值都是一样的。
序列化方法:1.直接str。O(n)时间。根的val+左序列化后的+右序列化后的。2.str+编号。O(1)时间。我们规定比如“235466”字符串有一个唯一的int标号(可以通过map.size()快速生成不同编号),这样就把无限长的str压缩成一个integer大小了。这种方法要求后序遍历,从而保证左右的先都被编好号了。
数据结构:Map<String, Integer> codes记录str到编号的转换(因为你整体都用编号生成str了,所以这里的str里包含的就是两个int+当前val,已经不会像原始情况下那么长了,此时可以说是O(1))Map<Integer, Integer> counts记录某个编号出现过多少次。
细节:
1.TreeNode加入ans的时间契机只在出现重复的第一次,count == 1的那次,之后不能重复加。
2.root == null的情况返回-1即可,优雅处理。
3.序列化做法时间复杂度O(n^2), 序列化+进一步编号时间复杂度O(n)。
实现:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public List<TreeNode> findDuplicateSubtrees(TreeNode root) { List<TreeNode> ans = new ArrayList<>(); postOrder(root, new HashMap<>(), new HashMap<>(), ans); return ans; } private int postOrder(TreeNode root, Map<String, Integer> codes, Map<Integer, Integer> counts, List<TreeNode> res) { if (root == null) { return -1; } int left = postOrder(root.left, codes, counts, res); int right = postOrder(root.right, codes, counts, res); String str = root.val + "#" + left + "#" + right; int code; if (codes.containsKey(str)) { // find same code again, deal and update. code = codes.get(str); if (counts.get(code) == 1) { res.add(root); } counts.put(code, counts.get(code) + 1); } else { // generate new code. code = codes.size(); codes.put(str, code); counts.put(code, 1); } return code; } }