代码随想录算法训练营day16 | 104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

136 阅读5分钟

104.二叉树的最大深度

给定一个二叉树,找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],返回它的最大深度 3 。

104. 二叉树的最大深度 - 力扣(Leetcode)

思路

在深度遍历中,将节点和当前层的层数depth作为参数进行迭代,当当前节点为空时,意味着完成了当前路径的遍历,当前路径的长度为depth -1,将该长度返回。
对于一个节点,它的深度与它的子树的深度相关,为其左、右子树的深度的较大值,因此,一个节点的深度为其左、右子树的深度的较大值,同理,一棵二叉树的深度为其根节点左、右子树的深度的较大值。

在层次遍历中,只要计算要二叉树的层数,即可计算该二叉树的深度。

代码

使用层序遍历,

class Solution {
    public int maxDepth(TreeNode root) {
        //方法1:层序遍历
        if(root==null){
            return 0;
        }

        if(root.left==null&&root.right==null){
            return 1;
        }

        Deque<TreeNode> que=new LinkedList<>();

        que.add(root);

        int depth=0;

        do{
            depth++;

            //加入结束符
            que.add(null);

            while(que.peek()!=null){
                TreeNode node=que.poll();

                if(node.left!=null){
                    que.add(node.left);
                }

                if(node.right!=null){
                    que.add(node.right);
                }
            }

            //清除 结束符
            que.poll();
        }while(!que.isEmpty());

        return depth;
    }
}

使用深度遍历,

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        int depth = travasal(root,1);

        return depth;
    }

    private int travasal(TreeNode cur,int depth){
        if(cur == null){
            return depth - 1;
        }

        int leftDepth=0, rightDepth=0;

        leftDepth = travasal(cur.left,  depth + 1);

        rightDepth =travasal(cur.right, depth + 1);

        return Math.max(leftDepth,rightDepth);

    }
}

559.n叉树的最大深度

给定一个 N 叉树,找到其最大深度。
最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。

559. N 叉树的最大深度 - 力扣(Leetcode)

思路

这道题使用层序遍历非常容易解决,解决方法与 104.二叉树的最大深度一样。

代码

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public int maxDepth(Node root) {
        if(root == null){
            return 0;
        }

        if(root.children.size() == 0){
            return 1;
        }

        Deque<Node> que = new LinkedList<>();
        Node node = null;
        int depth = 0;

        que.add(root);

        do{
            // 加入分隔符
            que.add(null);
            // 层数自增
            depth++;

            // 取出当前层的节点
            while((node = que.poll()) != null){
                // 将当前节点的所有孩子节点入队
                for(int i=0;i<node.children.size();i++){
                    que.add(node.children.get(i));
                }
            }
        }while(!que.isEmpty());

        return depth;
    }
}

111.二叉树的最小深度

给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。

111. 二叉树的最小深度 - 力扣(Leetcode)

思路

使用层次遍历可以轻松解决这个问题。在层次遍历中,如果出现了叶子节点,则当前深度为二叉树的最小深度。

  • 对根结点进行处理,
    • 如果根节点为null,即该二叉树是一棵空树,最小深度为00
    • 否则,如果根节点没有左右孩子,则根节点是一个叶子节点,则最小深度为11
    • 否则,进行层次遍历。
  • 在层次遍历中,在每一层中,
    • 加入分隔符,
    • 依次取出一个节点,直到取到分隔符,对于每一个节点,
    • 如果该节点同时无左右孩子,跳出循环,并返回当前层数;
    • 否则,将该节点的左右孩子(如果存在)入队。
  • 返回层数。

如果使用递归遍历,那么对于一个节点,有以下三种情况:

  • 有左子树,但无右子树,则 最小深度 = 左子树深度 + 1;
  • 有右子树,但无左子树,则 最小深度 = 右子树深度 + 1;
  • 同时有左右子树,或同时无左右子树,则 最小深度 = min(左子树深度, 右子树深度) + 1;此时,同时无左右子树是同时有左右子树的特殊情况,即 左子树深度 == 右子树深度 == 0 的情况。
  • 由于一个节点的深度与左右子树的深度相关,在计算当前节点的深度时需要知道左右子树的存在情况及其深度。因此,在递归遍历中使用左右中的后序遍历方式。

代码

层序遍历的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {

        if(root == null){
            return 0;
        }

        if(root.left == null && root.right == null){
            return 1;
        }

        int depth = 0;
        TreeNode node = null;

        Deque<TreeNode> que = new LinkedList<>();

        que.add(root);

        outer:do{
            que.add(null);
            depth++;

            while((node = que.poll()) != null){
                if(node.left == null && node.right == null){
                    break outer;
                }

                if(node.left != null){
                    que.add(node.left);
                }

                if(node.right != null){
                    que.add(node.right);
                }
            }

        }while(!que.isEmpty());

        return depth;

    }
}

递归方式的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {

        if(root == null){
            return 0;
        }

        // 没有左子树,有右子树
        // 最小深度为:右子树深度 + 1
        if(root.left == null && root.right != null){
            return 1 + minDepth(root.right);
        }

        // 有左子树,没有右子树
        // 最小深度为:左子树深度 + 1
        if(root.left != null && root.right ==null){
            return 1 + minDepth(root.left);
        }

        // 同时有左右子树,或者同时没有左右子树
        // 最小深度为: min(左子树深度,右子树深度) + 1
        return 1 + Math.min(minDepth(root.left),minDepth(root.right));

    }
}

222.完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

222. 完全二叉树的节点个数 - 力扣(Leetcode)

思路

一棵满二叉树的节点数为 2h12^h - 1,在一棵完全二叉树中,可以划分成多棵相同或不同高度的满二叉树组成(最小的一棵满二叉树可能是由一个节点组成),这样就可以利用满二叉树性质计算出树的节点个数。

判断一棵完全二叉树的子树是不是满二叉树的方法:
从该子树的根节点出发,分别计算它到子树最左边和最右边节点的节点数,如果相等,则该子树为满二叉树;否则,则这棵子树的最下面一层是不满的,这棵子树是一棵完全二叉树,它的节点数是左、右子树的节点数之和 + 1,从而再去通过判断左、右子树是不是满二叉树来计算该子树的节点数。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int countNodes(TreeNode root) {

        if(root == null){
            return 0;
        }

        TreeNode left = root.left;
        TreeNode right = root.right;

        int leftCount = 0, rightCount =0;

        while(left != null){
            leftCount++;
            left = left.left;
        }

        while(right != null){
            rightCount++;
            right = right.right;
        }

        if(leftCount == rightCount){
            // 即2^leftCount -1
            return (2 << leftCount) -1;
        }

        return countNodes(root.left) + countNodes(root.right) + 1;

    }

}