二叉树的深度和高度

1. 最大深度

给定一个二叉树, 找出其最大深度。二叉树的深度为根节点到最远叶子节点最长路径上的节点数。如二叉树 [ 3, 9, 20, null, null, 15, 7 ]的最大深度为3:

在这里插入图片描述

先看一个简单的情况:

在这里插入图片描述

对于节点 3, 最大深度自然是左右子节点 + 1, 左右子节点都有可能为空, 但只要有一个, 树的最大高度就是 1 + 1 = 2。然后再增加几个节点:

在这里插入图片描述

显然对于节点 20, 最大深度也是左右子节点 + 1, 左右子节点有可能为空, 只要有一个, 树的最大高度就是 1 + 1 = 2, 用代码表示就是:

int depth = 1 + max(leftDepth, rightDepth)

而对于节点 3, 则是左右子树深度最大的那个然后 + 1, 具体谁更大, 并不关心。所以对于节点 3 的判断逻辑就是:

int leftDepth = getDepth(node.left)	// 左子树高度
int rightDepth = getDepth(node.right)	// 右子树高度
int depth = 1 + max(leftDepth, rightDepth)	// 当前节点的高度

完整的代码:

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

继续分析这个题, 如果确定了树最大有几层是不是也就知道了最大深度, 所以直接套用层序遍历也可以解决该问题

public int maxDepth(TreeNode root) {
	if (root == null) {
		return 0;
	}
	Queue<TreeNode> queue = new LinkedList();
	queue.offer(root);
	int ans = 0;
	while (!queue.isEmpty()) {
		int size = queue.size;
		while (size > 0) {
			TreeNode node = queue.poll();
			if (node.left != null) {
				queue.offer(left);
			}
			if (node.right!= null) {
				queue.offer(right);
			}
			size--;
		}
		ans++;
	}
	return ans;
}

2. 判断平衡树

LeetCode110 判断平衡二叉树:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
这里的要求是二叉树每个节点的左右两个子树的高度差的绝对值不超过 1。先补充一个问题,高度和深度怎么区分呢?

  • 二叉树节点的深度: 指从根节点到该节点的最长简单路径的条数
  • 二叉树节点的高度: 指从该节点到叶子节点的最长简单路径的条数

在这里插入图片描述

先从最简单的情况分析:

在这里插入图片描述

显然只有两层的时候一定是平衡的, 因为对于节点 3, 左右孩子如果只有一个, 那高度差就是 1; 如果左右孩子都有或都没有, 那高度差为 0。

接着再增加一层, 如下图:

在这里插入图片描述

对于节点 3, 需要同时知道自己左右子树的高度差是否 < 2。

  • 当节点 root 左 / 右子树的高度差 < 2, 则返回节点 root 的左右子树最大高度加 1 ( max(left, right) + 1 )
  • 当节点 root 左 / 右子树的高度差 >= 2, 则返回 -1, 代表次数不是平衡树。
int left = recur(root.left);
int right = recur(root.right);
return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;

总和考虑几种情况, 完整的代码如下:

class Solution {
	public boolean isBalanced (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;
		}
	}
}

3. 最小深度

LeetCode111:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量,例如下面的例子返回结果为2。说明:叶子节点是指没有子节点的节点。

在这里插入图片描述

题目中所说: 最小深度是从根节点到最近叶子节点的最短路径上的节点数量, 也就是最小深度的一层必须有叶子节点, 因此不能通过直接将最大深度中的Max改为Min来解决。

核心问题依旧是分析终止条件:

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

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

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

除了递归方式, 也可以使用层序遍历, 只要在遍历时, 第一次遇到叶子节点就直接返回其所在层次即可。

public int minDepth(TreeNode root) {
	if (root == null) {
		return 0;
	}
	int minDepth = 0;
	Queue<TreeNode> queue = new LinkedList();
	queue.offer(root);
	while (!queue.isEmpty) {
		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.offer(t.left);
			}
			if (t.right!= null) {
				queue.offer(t.right);
			}
		}
	}
	return 0;
}

4. 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

在这里插入图片描述

相较于二叉树来说, 处理 N 叉树的不同点就是 N 叉树的节点比较多, 需要使用 List 存储, 遍历时用 for 循环。N 叉树的定义:

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) {
		this.val = val;
		this.children = children;
	}
}

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

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;
	}
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值