Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一.题目:
652. 寻找重复的子树 给定一棵二叉树
root,返回所有重复的子树。
对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。 如果两棵树具有相同的结构和相同的结点值,则它们是重复的。 示例 1:
输入: root = [1,2,3,4,null,2,4,null,null,4]
输出: [[2,4],[4]]
示例 2:
入: root = [2,1,1]
输出: [[1]]
示例 3:
输入: root = [2,2,2,3,null,3,null]
输出: [[2,3],[3]]
提示:
- 树中的结点数在
[1,10^4]范围内。 -200 <= Node.val <= 200
二、思路分析:
求解这道题目的核心在于:我们需要找到二叉树中重复的子树,那什么样的子树才能够称为重复的?就是这个子树的根以及它的左右子树与另外一个子树的值都完全相同就成为子树结构相同。那么我们怎么知道一个子树跟另外一个子树的结构相同?首先,我们需要知道它的左右子树是什么结构的,以及其他的子树都是什么样子的,所以我们就能够想到:后序遍历。
所以我们利用后序遍历的框架写出代码,然后把某子树给描述出来,这样我们就能够知道每个子树的模样,利用Map数据结构把每个子树的模样给记录下来,如果在递归中发现有同样结构的那么我们需要判断重复了几次,如果只有1次的话我们就可以利用结果集存放重复的子树即可。
三、代码:
/**
* @param {TreeNode} root
* @return {TreeNode[]}
*/
var findDuplicateSubtrees = function (root) {
//将子树用字符串描述出来,后序遍历将子树形成字符串
let res = []
let storage = new Map()
const traverse = function (root) {
if (root == null) return '#'
let left = traverse(root.left)
let right = traverse(root.right)
const SubTree = `${left},${right},${root.val}`
//将没有出现重复的放入Map中,如果一旦发现有重复的就纳入结果集,还需要注意多次出现重复的
let count = storage.get(SubTree) || 0
if (count == 1) {
res.push(root)
}
storage.set(SubTree, count + 1)
return SubTree
}
traverse(root)
return res
};
四、总结:
这道题目主要就是利用后序遍历把每个子树的样子给描述出来,然后通过比较得出结果,需要注意的是结果集的存放是子树本树而不是用于描述它的字符串序列,这个需要特别注意。