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

本节我们来聊聊树的经典问题——最大深度问题,下面我们就来看看二叉树和N叉树的的深度问题及它们的区别与联系

1. 二叉树的最大深度

首先看一下LeetCode104题最大深度:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点。例如上面的例子返回结果为最大深度为3。
我们先看一个简单情况:

   3	 	 3	   3 		  3  
  / \ 		/ 		\		 / \ 
 9  20 	   9	    20

对于node(3),最大深度自然是左右子结点+1,左右子节点有的可能为空,只要有一个,树的最大高度就是1+1=2。然后再增加几个结点:
算法通关村—轻松搞定树的最大深度问题_第1张图片
很显然相对于node(20),最大深度自然是左右子结点+1,左右子节点有的可能为空,只要有一个,树的最大高度就是1+1=2,用代码表示就是:
int depth = 1 + max(leftDepth, rightDepth);
(这里的depth的实际意义就是当前节点以下子树的最大深度)
而对于3,则是左右子树深度最大的那个然后再+1,具体谁更大,则不必关心。所以对于node(3)的判断逻辑就是:

int leftDepth = getDepth(node.left); // 左
int rightDepth = getDepth(node.right); // 右
int depth = 1 + max(leftDepth, rightDepth); // 中

那什么时候结束呢,这里仍然是root == null返回0就行了。至于入参,自然是要处理的子树的根节点root,而返回值则是当前root所在子树的最大高度。所以合在一起就是:

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

上面代码先拿到左右子树的结果再计算Math.max(left,right) + 1,这与后序遍历本质上一样的,因此可以看做后序遍历的拓展问题。
我们继续分析这个题,如果确定树最大有几层是不是也就知道最大深度了? 是的,直接套用层序遍历的代码就可以。
算法通关村—轻松搞定树的最大深度问题_第2张图片
具体做法是:我们修改2.2层次遍历中的分层方法,每获得一层增加一下层数就可以了。

    public static int maxDepth_2(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--;
            }
            ans++;
        }
        return ans;
    }

2. N叉树的最大深度

如果将二叉树换成N叉树又该怎么做呢?这就是LeetCode559.给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。

示例1:
输入:root = [1,null,3,2,4,null,5,6]
输出:3
示例2:
输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:5

算法通关村—轻松搞定树的最大深度问题_第3张图片
这道题就是将二叉树换成了N叉树,不同点就在于N叉树结点比较多,我们使用List存遍历时用for即可,我们先看N叉树的定义:

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;
	 }
}

这个题的实现和上一个题的最大区别就是处理子树时加了个处理List的for循环

   public static int maxDepth_N(NTreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.children == null || root.children.isEmpty()) {
            return 1;
        }
        LinkedList<Integer> height = new LinkedList<>();
        for (NTreeNode chd : root.children) {
            height.offer(maxDepth_N(chd));
        }
        return Collections.max(height) + 1;
    }

本题也可以使用层序遍历的方法进行求解,相比二叉树,这里对应每个节点的children是否为null,对于children中的元素是否为null,要考虑周全,这也是该方法符难点。(不会有人被空指针异常卡了2小时吧在这里插入图片描述)
解答如下:

public static int maxDepth_N1(NTreeNode root) {
       if (root == null)
           return 0;
       int N_depth = 0;
       Queue<NTreeNode> queue = new LinkedList<>();
       queue.add(root);
       while (!queue.isEmpty()) {
           int size = queue.size();
           for (int i = 0; i < size; i++) {
               NTreeNode t = queue.poll();
               if (t.children != null) {
                   for (NTreeNode chd : t.children) {
                       if (chd != null)
                           queue.add(chd);
                   }
               }
           }
           N_depth++;
       }
       return N_depth;
   }

你可能感兴趣的:(算法,算法,java,数据结构,笔记)