LeetCode 652. Find Duplicate Subtrees - 二叉树系列题17

该博客介绍了如何在给定的二叉树中有效地找到所有重复的子树。通过将每个子树转化为独特的字符串,然后利用字典记录出现次数,可以高效地找出重复的子树。在Python实现中,使用了前序遍历并以字符串形式保存子树结构,从而简化了问题的解决。这种方法避免了暴力比较,提高了算法效率。
摘要由CSDN通过智能技术生成

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个就表示该字符串对应的子树重复出现过。

对于如何将所有子树都转成对应的字符串结构,其实只要一次前序遍历就可以,从底向上构造字符串,每次在处理一个节点时,它的左右子树已经通过递归调用转成字符串了,因此只要把当前节点值转成字符串再与其左右子树字符串相连,中间通过空格或逗号分割开,这样就完成以当前节点为根节点的子树向字符串的转化。另外在递归遇到空节点时可以用一个特殊符号(如"#")来表示这样才能确保字符串唯一性。

class Solution:
    def findDuplicateSubtrees(self, root: Optional[TreeNode]) -> List[Optional[TreeNode]]:
        sub = {}
        
        def dfs(node):
            if not node:
                return "#"
            ret = str(node.val) + "," + dfs(node.left) + "," + dfs(node.right)
            if ret in sub:
                sub[ret].append(node)
            else:
                sub[ret] = [node]
            return ret
        dfs(root)
        
        res = []
        for s,nodes in sub.items():
            if len(nodes) > 1:
                res.append(nodes[0])
        return res

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值