2018-07-29 17:42:29

问题描述:

问题求解:

本题是要求寻找一棵树中的重复子树,问题的难点在于如何在遍历的时候对之前遍历过的子树进行描述和保存。

这里就需要使用之前使用过的二叉树序列化的手法,将遍历到的二叉树进行序列化表达,我们知道序列化的二叉树可以唯一的表示一棵二叉树,并可以用来反序列化。

想到这里其实问题就已经解决了一大半了, 我们只需要在遍历的过程中将每次的序列化结果保存到一个HashMap中,并对其进行计数,如果重复出现了,那么将当前的节点添加到res中即可。

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
List<TreeNode> res = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
helper(root, map, res);
return res;
} private String helper(TreeNode root, Map<String, Integer> map, List<TreeNode> res) {
if (root == null) return "#";
String str = root.val + "," + helper(root.left, map, res) + "," + helper(root.right, map, res);
if (map.containsKey(str)) {
if (map.get(str) == 1) res.add(root);
map.put(str, map.get(str) + 1);
}
else map.put(str, 1);
return str;
}

算法改进:

上述的算法基本可以在O(n)的时间复杂度解决问题,但是其中的字符串拼接是非常耗时的,这里可以对这个部分做出一点改进。如果我们不用序列化结果来表征一个子树,用一个id值来表征的话,那么就可以规避掉字符串拼接的问题。

这里直接使用id的size来进行id的分配,值得注意的是由于已经给null分配了0,那么每次分配的大小应该是size + 1。

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
List<TreeNode> res = new ArrayList<>();
Map<Long, Integer> id = new HashMap<>();
Map<Integer, Integer> map = new HashMap<>();
helper(root, id, map, res);
return res;
} private Integer helper(TreeNode root, Map<Long, Integer> id, Map<Integer, Integer> map, List<TreeNode> res) {
if (root == null) return 0;
Long key = ((long) root.val << 32) | helper(root.left, id, map, res) << 16 | helper(root.right, id, map, res);
if (!id.containsKey(key))
id.put(key, id.size() + 1);
int curId = id.get(key);
if (map.containsKey(curId)) {
if (map.get(curId) == 1) res.add(root);
map.put(curId, map.get(curId) + 1);
}
else map.put(curId, 1);
return curId;
}

寻找重复的子树 Find Duplicate Subtrees的更多相关文章

  1. LeetCode 652: 寻找重复的子树 Find Duplicate Subtrees

    LeetCode 652: 寻找重复的子树 Find Duplicate Subtrees 题目: 给定一棵二叉树,返回所有重复的子树.对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可. 两 ...

  2. [Swift]LeetCode652. 寻找重复的子树 | Find Duplicate Subtrees

    Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only ne ...

  3. Leetcode 652.寻找重复的子树

    寻找重复的子树 给定一棵二叉树,返回所有重复的子树.对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可. 两棵树重复是指它们具有相同的结构以及相同的结点值. 下面是两个重复的子树: 因此,你需 ...

  4. Java实现 LeetCode 652 寻找重复的子树(两个map的DFS)

    652. 寻找重复的子树 给定一棵二叉树,返回所有重复的子树.对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可. 两棵树重复是指它们具有相同的结构以及相同的结点值. 示例 1: 1 / \ ...

  5. [LeetCode] Find Duplicate Subtrees 寻找重复树

    Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, you only ne ...

  6. 652. Find Duplicate Subtrees找出重复的子树

    [抄题]: 就是出现了多次的子树,可以只包括一个点. Given a binary tree, return all duplicate subtrees. For each kind of dupl ...

  7. 【LeetCode】652. Find Duplicate Subtrees 解题报告(Python)

    [LeetCode]652. Find Duplicate Subtrees 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...

  8. LeetCode——Find Duplicate Subtrees

    Question Given a binary tree, return all duplicate subtrees. For each kind of duplicate subtrees, yo ...

  9. Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)

    Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和  ...

随机推荐

  1. 通用Dao方法

    import java.lang.reflect.Field; import java.sql.Connection; import java.sql.DatabaseMetaData; import ...

  2. c# 日期函数[string.Format----GetDateTimeFormats]格式

    DateTime dt = DateTime.Now;Label1.Text = dt.ToString();//2005-11-5 13:21:25Label2.Text = dt.ToFileTi ...

  3. Trove系列(五)—Trove的数据存储管理程序类型和版本管理功能介绍

    功能描述数据存储管理程序(Datastore)类型管理允许Trove的用户从操作者列出的名单中选择数据库存储管理程序和版本.操作者将可以控制数据库存储管理程序的类型,添加一个新的版本并去活一个老版本. ...

  4. Hive 大数据倾斜总结

    在做Shuffle阶段的优化过程中,遇 到了数据倾斜的问题,造成了对一些情况下优化效果不明显.主要是因为在Job完成后的所得到的Counters是整个Job的总和,优化是基于这些 Counters得出 ...

  5. input/radio/select等标签的值获取和赋值

    input/radio/select等标签的值获取和赋值,这几个是使用率最高的几个标签,获取值和赋值以及初始化自动填充数据和选择: 页面html: <div class=" " ...

  6. Linux基础命令---rmdir

    rmdir 删除一个空目录,可以同时删除途经的父目录,但是要确保父目录中没有其他内容. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. ...

  7. 01: RestfulAPI与HTTP

    1.1 RestfulAPI与HTTP简介 1.什么是RestfulAPI 1.REST直接翻译:表现层状态转移,实质就是一种面向资源编程的方法 2.REST描述的是在网络中client和server ...

  8. C_Learning(2)

    /指针 /指针变量指向一个变量的地址 /给指针变量赋的值只能是地址 /指针变量的赋值 /{ int a; int *p; p=&a; } or { int a; int *p=&a; ...

  9. C++ 表示一个区间值得方法

    C++中不允许这样的写法 85<= score <=100;你要想表示85<=score<=100的话只能这么写score>=85&&score<= ...

  10. AS语法

    SELECT COUNT(*) AS NumberOfOrders FROM Orders 含义:将选出的数据作为一列显示,列名为NumberOfOrders