力扣652_寻找重复的子树

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

两棵树重复是指它们具有相同的结构以及相同的结点值。
需要以列表的形式返回上述重复子树的根结点。
在这里插入图片描述
算法思想:
所有的二叉树问题,都逃不过那三个遍历,首先思考我们的问题属于三者中的哪一种。
首先,对于某一个节点,它应该做什么?
假如我现在站在这个2节点上,想知道以自己为根的子树是不是重复的,该不该加入重复列表中。
在这里插入图片描述
那么我要知道两个问题:

  1. 以我为根的子树长啥样
  2. 其他节点为根的子树长啥样

怎么知道自己啥样呢,如果我知道我的左右他们啥样,再加上我自己,不就是整棵树的样子了嘛,所以此题用的是三种遍历中的后序遍历,类似与后序求一棵树的节点,我们给出方法(注:描述一颗树的形状采用序列化)

String traverse(TreeNode root) {
    // 对于空节点,可以用一个特殊字符表示
    if (root == null) {
        return "#";
    }
    // 将左右子树序列化成字符串
    String left = traverse(root.left);
    String right = traverse(root.right);
    /* 后序遍历代码位置 */
    // 左右子树加上自己,就是以自己为根的二叉树序列化结果
    String subTree = left + "," + right + "," + root.val;
    return subTree;
}

那么第二个问题,怎么知道其他节点长啥样呢?
用备忘录呗,把他们都记下来,统计统计出现的次数,不就知道哪些重复了嘛

代码实现:

class Solution {

    HashMap<String,Integer> memo = new HashMap<>(); //存储所有已经看过的树
    LinkedList<TreeNode> res = new LinkedList<>(); //存储重复子树

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        traverse(root);
        return res;
    }

    //描述一棵树的样子 序列化
    public String traverse(TreeNode root){

        //使用#表示空节点
        if(root == null) return "#";

        //先知道它的左子树啥样
        String left = traverse(root.left);
        //再知道它的右子树啥样
        String right = traverse(root.right);
        //于是我们就知道这棵树啥样了
        String subTree = left + "," + right + "," + root.val;

        //看看备忘录里面有没有这个节点
        int freq = memo.getOrDefault(subTree, 0); //Map的getOrDefault方法,如果不存在这个键值,默认为0
        //只在出现第一次重复的时候加一次
        if(freq == 1) {
            res.add(root);
        }
        memo.put(subTree, freq+1);
        
        return subTree;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值