一、104 二叉树的最大深度
思路:首先是使用层序遍历的模板,在层序遍历的那一节已经做过;其次是使用迭代法,应该使用后序迭代,先求左子树和右子树的高度中较大的一个,然后加上1就是这个子树的最大高度。这里其实求的是二叉树的高度,正好也就是最大的深度。
代码:
var maxDepth = function(root) {
var depth = 0;
if (!root) {
return 0;
}
// 处理逻辑:左右子树最高的高度加一
var leftDepth = maxDepth(root.left);
var rightDepth = maxDepth(root.right);
depth = Math.max(leftDepth,rightDepth) + 1;
return depth;
};
559 N叉树的最大深度
题目链接:https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/
思路:类似上一题
代码:
var maxDepth = function(root) {
if (!root) {
return 0;
}
// 这是起始的值,所以应该是0
var maxChildDepth = 0;
for (const child of root.children) {
// 这里把它单独拿出来定义,可以减少一半的递归时间
const childDepth = maxDepth(child);
maxChildDepth = Math.max(maxChildDepth, childDepth);
}
return maxChildDepth + 1;
};
二、111 二叉树的最小深度
思路:可以用层序遍历,这里我们主要研究后序遍历递归法,详情见代码注释。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点。我觉得还是用层序遍历更简单一点。
代码:
var minDepth = function(root) {
var depth = 0;
// 如果本身为空,返回0
if (!root) {
return 0;
}
// 如果左右子树都为空,则返回1
else if (!root.left && !root.right) {
return 1;
}
// 如果左子树为空右子树不为空,则返回右子树的最小深度
else if (!root.left && root.right){
return minDepth(root.right) + 1;
}
// 如果右子树为空左子树不为空,则返回左子树的最小深度
else if (root.left && !root.right) {
return minDepth(root.left) + 1;
}
// 递归处理:如果左右子树都需要计算,则得出最小的一个之后再加一
depth = Math.min(minDepth(root.left), minDepth(root.right)) + 1;
return depth;
};
三、222 完全二叉树的节点个数
思路:首先想到的是可以利用层序遍历来进行计算,只要碰到空指针就可以返回了。其次,如果使用递归的方法,那么有几种情况,第一种是有左子树而没有右子树,返回2;第二种两个子树都没有,返回1;最后一种是两个子树都有,那么进入递归循环,求其左右子树的节点个数和加一。如果用完全二叉树的特性,上面的n-1层都是满的,最下面的一层是从左到右依次排开,完全二叉树在向下遍历的过程当中必然会遇到这一子树是满二叉树的情况,那么这时候我们就可以使用公式,通过深度来直接计算这个子树的节点数量。
层序遍历代码,时间复杂度O(n):
var countNodes = function(root) {
if (!root) {
return 0;
}
var queue = [];
queue.push(root);
var index = 0;
while (index !== queue.length) {
var cur = queue[index];
if (cur.left){
queue.push(cur.left);
}
if (cur.right) {
queue.push(cur.right);
}
index += 1;
}
return index;
};
后序遍历迭代法:
var countNodes = function(root) {
if (!root) {
return 0;
}
else if (!root.left && !root.right) {
return 1;
}
else if (root.left && !root.right) {
return 2;
}
return countNodes(root.left) + countNodes(root.right) + 1;
};
利用完全二叉树特性的代码:
var countNodes = function(root) {
if (!root) {
return 0;
}
// 判断一个子树是不是满二叉树,如果是的话需要将这个满二叉树的节点数量作为返回条件
var left = root.left;
var right = root.right;
var leftDepth = 0;
var rightDepth = 0;
while (left) {
left = left.left;
leftDepth += 1;
}
while (right) {
right = right.right;
rightDepth += 1;
}
// 如果向左遍历的深度和向右遍历的深度相等,则可以认为是满二叉树
if (leftDepth == rightDepth) {
return Math.pow(2, leftDepth + 1) - 1;
}
return countNodes(root.left) + countNodes(root.right) + 1;
}
今日学习时长:2.5h左右
总结:最大深度和最小深度不同,最大深度可以直接套用后序遍历递归的模板,但最小深度需要注意的是如果一个子树为空另一个子树不为空是需要单独计算的。另外,需要记住完全二叉树的特性,即向右或向左遍历总会遇见满二叉树,这时候可以直接利用2^n - 1的公式返回节点数量。再刷的时候需要注意111和222题。