二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
而根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。
这一点其实是很多同学没有想清楚的,很多题解同样没有讲清楚。
遍历的顺序一定是左右中,中间是处理的过程(把孩子节点的深度返回给父节点)
简单
给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数
任何一个节点的高度,都是它左右子树最大高度加一,所以要知道根节点的高度,肯定要知道它子树的高度,要知道它子树的高度,肯定要知道它子树的子树的高度……因此,高度肯定是要从最下面往上面算出来的,可以通过递归,找到最深层的那个节点,然后一层一层地返回,直到抵达根节点,这就是要使用后序遍历的原因
单层递归的逻辑:先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。
class Solution {
public int maxDepth(TreeNode root) {
return getDepth(root);
}
public int getDepth(TreeNode node){
if (node == null) {
return 0;
}
int leftDepth = getDepth(node.left) ;
int rightDepth = getDepth(node.right);
return Math.max(leftDepth, rightDepth) + 1;
}
}
// 层序遍历法
class Solution {
public int maxDepth(TreeNode root) {
int res = 0;
if (root == null) {
return res;
}
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
// while 循环控制从上向下一层层遍历
while(!q.isEmpty()){
int size = q.size();
TreeNode curNode;
res++;//该层深度自增
// for 循环控制每一层从左向右遍历
for (int i = 0; i < size; i++) {
curNode = q.poll();
// 不断地把该层的不为空的孩子结点加入队列
if(curNode.left != null) q.offer(curNode.left);
if(curNode.right != null) q.offer(curNode.right);
}
}
return res;
}
}
简单
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点
在处理节点的过程中,最大深度很容易理解,最小深度就不那么好理解,如图:
这就重新审题了,题目中说的是:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。,注意是叶子节点。
什么是叶子节点,左右孩子都为空的节点才是叶子节点!
如果这么求的话,没有左孩子的分支会算为最短深度。
所以,如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。
class Solution {
public int minDepth(TreeNode root) {
int minDep = getMin(root);
return minDep;
}
public int getMin(TreeNode node) {
if (node == null) {
return 0;
}
if (node.left == null && node.right == null) {
return 1;
}
if (node.left == null && node.right != null) {
return getMin(node.right) + 1;
}
if (node.left != null && node.right == null) {
return getMin(node.left) + 1;
}
return Math.min(getMin(node.left), getMin(node.right)) + 1;
}
}
// 层序遍历法
class Solution {
public int minDepth(TreeNode root) {
int minDep = 0;
if (root == null) {
return minDep;
}
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
// while 循环控制从上向下一层层遍历
while(!q.isEmpty()){
int size = q.size();
TreeNode curNode;
minDep++;//该层深度自增
// for 循环控制每一层从左向右遍历
for (int i = 0; i < size; i++) {
curNode = q.poll();
// 当发现一个叶子节点时就可以返回结果了
if (curNode.left == null && curNode.right == null) return minDep;
// 不断地把该层的不为空的孩子结点加入队列
if(curNode.left != null) q.offer(curNode.left);
if(curNode.right != null) q.offer(curNode.right);
}
}
return minDep;
}
}
简单
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
层序遍历法可以秒了。
递归的话,和求最小深度比较类似,可以如下:
利用完全二叉树的特性计算节点的方法(这个方法我没自己写,我觉得非常鸡肋,大概就是说,完全二叉树一定是由满二叉树组成的,满二叉树的节点数公式为:2^深度数 - 1,所以可以往下递归),写法如下:
class Solution {
/**
* 针对完全二叉树的解法
*
* 满二叉树的结点数为:2^depth - 1
*/
public int countNodes(TreeNode root) {
if (root == null) return 0;
TreeNode left = root.left;
TreeNode right = root.right;
int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
while (left != null) { // 求左子树深度
left = left.left;
leftDepth++;
}
while (right != null) { // 求右子树深度
right = right.right;
rightDepth++;
}
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
}
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
递归通用写法:
// 通用递归解法
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int leftNum = countNodes(root.left);
int rightNum = countNodes(root.right);
return leftNum + rightNum + 1; // 加一是加上本身节点,整体上是一个后序遍历
}
}