算法通关村 —— 轻松搞定树的深度问题

目录

树的深度问题

一 最大深度问题

二 最小深度

三 N 叉树的最大深度


树的深度问题

在此之前,我们已经学习了很多树的基础知识和经典算法,今天让我们一起来学习几道比较有难度的题目——有关树的深度和高度问题,这几道对递归的要求高一些,一起来看看吧!

一 最大深度问题

给定一个二叉树,找出其最大深度。二叉树最大深度为根节点到最远叶子节点的最长路径上的节点数。例如下面的例子返回结果为最大深度为3.

        3
       / \
      9  20
        /  \
       15   7

实现方法其实很简单,只需要通过递归的方法一直遍历到root == null返回0,然后每遍历完当前节点的左右节点,返回左右子树较大的深度即可。递归遍历完所有节点则可得到该树的最大深度。实现代码如下:

public static int maxDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    // 访问左节点查看左子树最大深度
    int leftHeight = maxDepth(root.left);
    // 访问右节点查看右子树最大深度
    int rightHeight = maxDepth(root.right);
    // 返回左右子树较大的深度加上当前节点作为该节点子树的最大深度
    return Math.max(leftHeight, rightHeight) + 1;
}

当然除了这种做法,还有其他的解决思路,假如我们知道了树的层数那是不是就等于知道最大深度了。没错,所以哦我们只需要利用层序遍历的代码即可。代码如下:

public static int maxDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    queue.offer(root);
    int ans = 0;
    while (!queue.isEmpty()) {
        //size表示某一层的所有元素数
        int size = queue.size();
        //size=0 表示一层访问完了
        while (size > 0) {
            TreeNode node = queue.poll();
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
            // 每遍历完该层的一个节点,该节点出队,左右节点入队,该层节点数减一
            size--;
        }
        // 每遍历完一层,则最大层数加1
        ans++;
    }
    return ans;
}

二 最小深度

既然树有最大深度,那就会有最小深度。给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量,例如下面的例子返回结果3。

注!:最小深度的一层必须要有节点,最小深度指的是从根节点到最近叶子节点的最短路径上的节点数量!!!

这里的核心问题主要是分析终止条件:

⚪ 如果左右子树都为空,则说明该节点为叶子节点,返回其初始深度值1。

⚪ 如果左子树为空,右子树不为空,则最小深度为右子树深度+1。

⚪ 如果右子树为空,左子树不为空,则最小深度为左子树深度+1。

⚪ 如果左右子树都不为空,返回左右子树深度的最小值 + 1,则得到当前子树最小深度

代码如下:
 

public int minDepth(TreeNode root) {
    if (root == null) return 0;
    // 如果遍历到叶子节点,则返回当前节点深度1
    if(root.left == null && root.right == null) return 1;
    int mindepth = Integer.MAX_VALUE; // 存储当前最小子树深度
    // 遍历左右子树,寻找当前最小深度
    if(root.left != null) mindepth = Math.min(mindepth, minDepth(root.left));
    if(root.right != null) mindepth =  Math.min(mindepth, minDepth(root.right));
    // 返回最小子树深度,为该节点的最小子树深度加上本身深度1
    return mindepth + 1;
}

上面的方法是通过递归从叶子节点出发,不断判断子树的最小深度,最终得到整棵树的最小深度。除了这个方法,我们同样也可用层次遍历来解决,只要在层次遍历时第一次遇到子节点直接返回其所在层次即可,所以只需改一下层次遍历的代码即可,如下:

public static int minDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int minDepth = 0;

    LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    while (queue.size() > 0) {
        //获取当前队列的长度,这个长度相当于 当前这一层的节点个数
        int size = queue.size();
        minDepth++;
        for (int i = 0; i < size; ++i) {
            TreeNode t = queue.remove();
            if (t.left == null && t.right == null) {
                // 当遍历到叶子节点,返回当前的层数,即为最小深度
                return minDepth;
            }
            if (t.left != null) {
                queue.add(t.left);
            }
            if (t.right != null) {
                queue.add(t.right);
            }
        }
    }
    return 0;
}

三 N 叉树的最大深度

前面我们研究的都是二叉树,那要是换成N叉树呢,其实也是大差不差的,只不过树结构改变了而已,原来是遍历左右孩子,现在需要遍历节点的所有子节点,也就是遍历该节点所有子节点的列表而已,遍历时多加了个List的for循环。具体实现代码如下:

class Solution {
    public int maxDepth(Node root) {
        if(root == null) return 0;
        // 遍历到叶子节点,返回当前一个深度
        else if(root.children.isEmpty()) return 1; 
        else{
            // 若不是叶子节点,则要再访问自己的所有子节点
            List<Integer> heights = new LinkedList<>(); // 存放每个子节点的深度
            for (Node node : root.children){
                heights.add(maxDepth(node));
            }
            return Collections.max(heights) + 1; // 返回当前子树最大深度
        }
    }
   class Node {
        public int val;
        public  List<Node> children;
        public Node(){}
        public Node(int _val) {
            this.val = _val;
        }

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值