码迷,mamicode.com
首页 > 其他好文 > 详细

865. 具有所有最深节点的最小子树

时间:2021-05-24 02:49:50      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:左右子树   递归   dai   else   否则   层序遍历   src   开始   lis   

难度 medium
给定一个根为 root 的二叉树,每个节点的深度是 该节点到根的最短距离 。

如果一个节点在 整个树 的任意节点之间具有最大的深度,则该节点是 最深的 。

一个节点的 子树 是该节点加上它的所有后代的集合。

返回能满足 以该节点为根的子树中包含所有最深的节点 这一条件的具有最大深度的节点。

注意:本题与力扣 1123 重复:https://leetcode-cn.com/problems/lowest-common-ancestor-of-deepest-leaves/

示例 1:

技术图片

输入:root = [3,5,1,6,2,0,8,null,null,7,4]
输出:[2,7,4]
解释:
我们返回值为 2 的节点,在图中用黄色标记。
在图中用蓝色标记的是树的最深的节点。
注意,节点 5、3 和 2 包含树中最深的节点,但节点 2 的子树最小,因此我们返回它。
示例 2:

输入:root = [1]
输出:[1]
解释:根节点是树中最深的节点。
示例 3:

输入:root = [0,1,3,null,2]
输出:[2]
解释:树中最深的节点为 2 ,有效子树为节点 2、1 和 0 的子树,但节点 2 的子树最小。

提示:

树中节点的数量介于 1 和 500 之间。
0 <= Node.val <= 500
每个节点的值都是独一无二的。

这道题我两个题解都是看的网上的资料,一开始给自己设置了20分钟,做不出来,后来就在网上看了答案,隔了一天之后再去做,才做好的。
解题思路1:这个题解非常朴素,就是一个这样的思想:用一个findHeight函数,负责找到某个节点的高度,然后从root节点开始遍历整棵树,如果root的左右子树的高度是一样的,那当前节点就是结果,因为左子树和右子树是没有公共节点的,如果他们高度一致,那一定是两边各有一个最深的节点,所以当前节点肯定就是结果了,否则符合条件的结果肯定是在高度较高的那棵子树中,因此我们比较左右子树的高度,然后对较高的那棵子树进行递归调用,从而找到目标。

代码 t100 s91 java

class Solution {
    public TreeNode subtreeWithAllDeepest(TreeNode root) {
        if(root==null) return null;
        int leftHeight = findHeight(root.left);
        int rightHeight = findHeight(root.right);
        if(leftHeight==rightHeight) return root;
        else if(leftHeight>rightHeight) return subtreeWithAllDeepest(root.left);
        else return subtreeWithAllDeepest(root.right);
    }

    public int findHeight(TreeNode node){
        if(node==null) return 0;
        return Math.max(findHeight(node.left), findHeight(node.right)) + 1;
    }
}

解题思路2:这个题解是在国外的网站上看到的,我其实一开始用的就是这个思路,但是在子节点和父节点之间建立映射关系这个方法我一直没有想到,所以也没写出来。说一下思路:用层序遍历的方法,遍历整棵树,最深的那一层肯定是最后遍历到的,我们用HashMap建立子节点和父节点之间的关系,用一个单向队列进行从左到右的遍历,用一个动态数组来储存每一层层序遍历得到的所有节点,遍历一层之后,如果q已经为空,那说明已经是最后一层,即将退出while(!q.isEmpty())的循环,此时直接用break结束语句,否则更新存储节点的动态数组,也就是这个动态数组中始终保存着最近遍历的那一层的所有节点。结束层序遍历之后,动态数组中就保存着最后一层的所有节点,我们再进入一个while循环,用一个HashSet保存动态数组中所有节点,因为HashSet具有去重的作用,当HashSet的大小为1时,说明已经找到了符合条件的节点,直接返回,否则就把节点数组i位置的节点设置为其父节点,这里用前面的HashMap来找到父节点,并重新回到上一步,新建一个HashSet,并往里面添加节点数组所有节点,直到HashSet的大小为1退出。

代码 t20 s16 java

class Solution {
    public TreeNode subtreeWithAllDeepest(TreeNode root) {
        Queue<TreeNode> q = new LinkedList<>();
        HashMap<TreeNode, TreeNode> map = new HashMap<>();
        ArrayList<TreeNode> nodes = new ArrayList<>();
        q.add(root);
        nodes.add(root);
        while(!q.isEmpty()){
            int sz = q.size();
            ArrayList<TreeNode> tmp = new ArrayList<>();
            for(int i=0; i<sz; i++){
                TreeNode t = q.poll();
                if(t.left!=null){
                    q.add(t.left);
                    tmp.add(t.left);
                    map.put(t.left, t);
                }
                if(t.right!=null){
                    q.add(t.right);
                    tmp.add(t.right);
                    map.put(t.right, t);
                }
            }
            if(q.isEmpty()) break;
            else nodes = tmp;
        }
        if(nodes.size()==1) return nodes.get(0);
        while(true){
            HashSet<TreeNode> set = new HashSet<>();
            set.addAll(nodes);
            if(set.size()==1) return nodes.get(0);
            for(int i=0; i<nodes.size(); i++){
                nodes.set(i, map.get(nodes.get(i)));
            }
        }
    }
}

参考资料
https://leetcode-cn.com/problems/smallest-subtree-with-all-the-deepest-nodes/solution/cu-su-yi-dong-zhi-jie-kan-dai-ma-he-zhu-z4exw/
https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes/solution/

865. 具有所有最深节点的最小子树

标签:左右子树   递归   dai   else   否则   层序遍历   src   开始   lis   

原文地址:https://www.cnblogs.com/zhengxch/p/14747288.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!