加载中...
652-寻找重复的子树(Find Duplicate Subtrees)
发表于:2021-12-03 | 分类: 中等
字数统计: 982 | 阅读时长: 4分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/find-duplicate-subtrees

英文原文

Given the root of a binary tree, return all duplicate subtrees.

For each kind of duplicate subtrees, you only need to return the root node of any one of them.

Two trees are duplicate if they have the same structure with the same node values.

 

Example 1:

Input: root = [1,2,3,4,null,2,4,null,null,4]
Output: [[2,4],[4]]

Example 2:

Input: root = [2,1,1]
Output: [[1]]

Example 3:

Input: root = [2,2,2,3,null,3,null]
Output: [[2,3],[3]]

 

Constraints:

  • The number of the nodes in the tree will be in the range [1, 10^4]
  • -200 <= Node.val <= 200

中文题目

给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。

两棵树重复是指它们具有相同的结构以及相同的结点值。

示例 1:

        1
       / \
      2   3
     /   / \
    4   2   4
       /
      4

下面是两个重复的子树:

      2
     /
    4

    4

因此,你需要以列表的形式返回上述重复子树的根结点。

通过代码

官方题解

方法一:深度优先搜索【通过】

思路

序列化二叉树。

[snippet1-Python]
1 / \ 2 3 / \ 4 5

例如上面这棵树序列化结果为 1,2,#,#,3,4,#,#,5,#,#。每棵不同子树的序列化结果都是唯一的。

算法

使用深度优先搜索,其中递归函数返回当前子树的序列化结果。把每个节点开始的子树序列化结果保存在 $map$ 中,然后判断是否存在重复的子树。

[solution1-Python]
class Solution(object): def findDuplicateSubtrees(self, root): count = collections.Counter() ans = [] def collect(node): if not node: return "#" serial = "{},{},{}".format(node.val, collect(node.left), collect(node.right)) count[serial] += 1 if count[serial] == 2: ans.append(node) return serial collect(root) return ans
[solution1-Java]
class Solution { Map<String, Integer> count; List<TreeNode> ans; public List<TreeNode> findDuplicateSubtrees(TreeNode root) { count = new HashMap(); ans = new ArrayList(); collect(root); return ans; } public String collect(TreeNode node) { if (node == null) return "#"; String serial = node.val + "," + collect(node.left) + "," + collect(node.right); count.put(serial, count.getOrDefault(serial, 0) + 1); if (count.get(serial) == 2) ans.add(node); return serial; } }

复杂度分析

  • 时间复杂度:$O(N^2)$,其中 $N$ 是二叉树上节点的数量。遍历所有节点,在每个节点处序列化需要时间 $O(N)$。

  • 空间复杂度:$O(N^2)$,count 的大小。

方法二:唯一标识符【通过】

思路

假设每棵子树都有一个唯一标识符:只有当两个子树的 id 相同时,认为这两个子树是相同的。

一个节点 node 的左孩子 id 为 x,右孩子 id 为 y,那么该节点的 id 为 (node.val, x, y)

算法

如果三元组 (node.val, x, y) 第一次出现,则创建一个这样的三元组记录该子树。如果已经出现过,则直接使用该子树对应的 id。

[solution2-Python]
class Solution(object): def findDuplicateSubtrees(self, root): trees = collections.defaultdict() trees.default_factory = trees.__len__ count = collections.Counter() ans = [] def lookup(node): if node: uid = trees[node.val, lookup(node.left), lookup(node.right)] count[uid] += 1 if count[uid] == 2: ans.append(node) return uid lookup(root) return ans
[solution2-Java]
class Solution { int t; Map<String, Integer> trees; Map<Integer, Integer> count; List<TreeNode> ans; public List<TreeNode> findDuplicateSubtrees(TreeNode root) { t = 1; trees = new HashMap(); count = new HashMap(); ans = new ArrayList(); lookup(root); return ans; } public int lookup(TreeNode node) { if (node == null) return 0; String serial = node.val + "," + lookup(node.left) + "," + lookup(node.right); int uid = trees.computeIfAbsent(serial, x-> t++); count.put(uid, count.getOrDefault(uid, 0) + 1); if (count.get(uid) == 2) ans.add(node); return uid; } }

复杂度分析

  • 时间复杂度:$O(N)$,其中 $N$ 二叉树上节点的数量,每个节点都需要访问一次。

  • 空间复杂度:$O(N)$,每棵子树的存储空间都为 $O(1)$。

统计信息

通过次数 提交次数 AC比率
35842 62803 57.1%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
二叉树的序列化与反序列化 困难
序列化和反序列化二叉搜索树 中等
根据二叉树创建字符串 简单
上一篇:
650-只有两个键的键盘(2 Keys Keyboard)
下一篇:
653-两数之和 IV - 输入 BST(Two Sum IV - Input is a BST)
本文目录
本文目录