Skip to content
本页目录

0652-寻找重复的子树

题目描述

https://leetcode.cn/problems/find-duplicate-subtrees

给定一棵二叉树 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

思路分析

起初想到的是暴力解法,用dfs遍历每个节点,然后从那个节点再开始遍历所有节点,最后判断两棵树是否相等,代码如下: 此代码对去重部分逻辑有问题(比如示例1,第3个4的节点,还会被加入),且节点数时 1-10^4,O(n^3)的时间复杂度会超时

csharp
public class Solution {

    List<TreeNode> list = new List<TreeNode>();
    List<TreeNode> listAll = new List<TreeNode>();

    private bool IsSubTree(TreeNode node1, TreeNode node2){
        if(node1 == null && node2 == null){
            return true;
        }
        if(node1 == node2){
            return false;
        }
        if(node1 == null || node2 == null){
            return false;
        }
        //Console.WriteLine("node1val:{0},node2val:{1}",node1.val,node2.val);
        if(node1.val != node2.val){
            return false;
        }
        return IsSubTree(node1.left,node2.left) && IsSubTree(node1.right , node2.right);
    }

    private void dfs(TreeNode node1, TreeNode node2){
        if(node1 == null || node2 == null){
            return;
        }
        //Console.WriteLine("dfs:{0} {1}",node1.val,node2.val);
        if(IsSubTree(node1,node2)){
            if(!listAll.Contains(node1) && !listAll.Contains(node1)){
                list.Add(node1);
                listAll.Add(node1);
                listAll.Add(node2);
            }
        }
        dfs(node1.left,node2);
        dfs(node1.right,node2);
        dfs(node1,node2.left);
        dfs(node1,node2.right);
    }

    public IList<TreeNode> FindDuplicateSubtrees(TreeNode root) {
        dfs(root,root);
        return list;
    }
}

题解

查看官方题解,使用序列化的方式,将已有的序列化作为key放入hash表中,这样判断key是否存在就知道。 序列化的方式是 节点值(左节点)(右节点)

csharp
public class Solution {

    Dictionary<string,TreeNode> dict = new Dictionary<string,TreeNode>();
    List<TreeNode> result = new List<TreeNode>();

    private string dfs(TreeNode root){
        if(root == null){
            return "";
        }

        StringBuilder sb = new StringBuilder();
        sb.Append(root.val);
        sb.Append("(");
        sb.Append(dfs(root.left));
        sb.Append(")");
        sb.Append("(");
        sb.Append(dfs(root.right));
        sb.Append(")");
        string key = sb.ToString();
        if(dict.ContainsKey(key)){
            if(!result.Contains(dict[key])){
                result.Add(dict[key]);
            }
        }
        else{
            dict.Add(key,root);
        }
        return key;
    }

    public IList<TreeNode> FindDuplicateSubtrees(TreeNode root) {
        dfs(root);
        return result;
    }
}

Released under the MIT License.