编程导航算法通关村第八关 | 二叉树的高度和深度问题

94 阅读2分钟

最大深度问题

. - 力扣(LeetCode)

用代码表示就是:

int depth = 1 + max(leftDepth, rightDepth);

而对于3,则是左右子树深度最大的那个然后再+1,具体谁更大,则不必关心

那什么时候结束呢,这里仍然是root == null返回0就行了。至于入参,自然是要处理的子树的根节点root,

而返回值则是当前root所在子树的最大高度。所以合在一起就是:

public 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 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--;
        }
        ans++;
    }
    return ans;
}

判断平衡树

. - 力扣(LeetCode)

  • 当节点root 左 / 右子树的高度差 < 2,则返回节点 root 的左右子树中最大高度加 1 ( max(left, right) + 1 );参考上面的高度和深度的对比图思考一下,这里为什么是最大高度?
  • 当节点root 左 / 右子树的高度差 ≥2 :则返回 -1 ,代表 此子树不是平衡树

代码:

public boolean isBalance(TreeNode root) {
    return height(root) >= 0;
}
public int height(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int leftHeight = height(root.left);
    int rightHeight = height(root.right);
    if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {
        return -1;
    }else {
        return Math.max(leftHeight, rightHeight) + 1;
    }
}

最小深度

. - 力扣(LeetCode)

最小深度是从根节点到最近叶子节点的最短路径上的节点数量,也就是最小深度的一层必须要有叶子结点,因此不能直接用。

这里的核心问题仍然是分析终止条件:

  • 如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
  • 反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。

最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。

代码如下:

递归:

public int minDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    if (root.left == null && root.right == null) {
        return 1;
    }
    int min_depth = Integer.MAX_VALUE;
    if (root.left != null) {
        min_depth = Math.min(minDepth(root.left), min_depth);
    }
    if (root.right != null) {
        min_depth = Math.min(minDepth(root.right), min_depth);
    }

    return min_depth + 1;
}

层序遍历:

public 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叉树的最大深度

. - 力扣(LeetCode)

这道题就是将二叉树换成了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;
    }
}

代码:

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 item : root.children) {
            heights.add(maxDepth(item));
        }
        return Collections.max(heights) + 1;
    }
}