题目
思路
迭代法
从题目可知,其实二叉树的深度和二叉树的层数是一样的。
那么,就可以在二叉树的层序遍历时,遍历每层时用count来计数。
var maxDepth = function(root) {
if(root == null) {
return 0;
}
let queue = [];
let size = 0;
queue.push(root);
let count = 0;
while(queue.length != 0) {
size = queue.length;
while(size-- > 0) {
let node = queue.shift();
if(node.left != null) {
queue.push(node.left);
}
if(node.right != null) {
queue.push(node.right);
}
}
count++;
}
return count;
};
递归法
- 后序遍历,收集左右子树信息,之后再整合
- 收集以下信息:
-
- 左子树-有几层
- 右子树-有几层
- 在左子树、右子树中挑层数更多的,加上根节点本身,加1返回。
var maxDepth = function(root) {
if(root == null) {
return 0;
}
let leftNum = maxDepth(root.left);
let rightNum = maxDepth(root.right);
return leftNum > rightNum ? leftNum + 1: rightNum + 1;
};
题目
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
思路
- 后序遍历,收集左子树和右子树的信息
- 收集以下信息:
-
- 左子树-深度
- 右子树-深度
- 整合:左子树、右子树中深度较小,+1
难点
上面的这种情况,如果每层的处理如果只是将deth小的收集过来。
那么,最终return的是左边的根节点到空节点的距离。
这样是不对的,因为深度应该返回的是根节点到叶子节点的距离。
所以,上面这种一个孩子是null,另一个孩子有值的情况要单独处理。
if(leftDeth == 0 && rightDeth == 0) return 1; // 谁是空节点,就不返回它,而返回另一个节点 if(leftDeth == 0 || rightDeth == 0) { return leftDeth == 0 ? rightDeth + 1: leftDeth + 1; }
完整代码
var minDepth = function(root) {
if(root == null) {
return 0;
}
let leftDeth = minDepth(root.left);
let rightDeth = minDepth(root.right);
// 这两个if是为了解决这个问题:
// 当一个节点左节点==null,右节点有节点时,
// 处理的逻辑会自动把左节点return的0取上,但实际上这里并没有一层。
if(leftDeth == 0 && rightDeth == 0) return 1;
if(leftDeth == 0 || rightDeth == 0) {
return leftDeth == 0 ? rightDeth + 1: leftDeth + 1;
}
return leftDeth < rightDeth ? leftDeth+1 : rightDeth+1;
};
普通二叉树的节点个数
- 后序遍历,收集信息
- 收集以下信息:
-
- 左子树-有多少个节点
- 右子树-有多少个节点
- 整合:一共有多少个节点
var countNodes = function(root) { if(root == null) { return 0; } let leftNum = countNodes(root.left); let rightNum = countNodes(root.right); return leftNum + rightNum + 1; };
完全二叉树的节点
上面计算普通二叉树的节点数,每个节点都要遍历一遍,时间复杂度O(n)
还有一种方法,时间复杂度是O(logn * logn)。
这种方法,利用了完全二叉树的特性:一棵二叉树可以剪成多棵子树为满二叉树的组合,满二叉树的节点数用公式
2 * h - 1就可以计算(h为二叉树的高度)。
也就是说,通过递归,把完全二叉树剪成满二叉树,然后用公式计算有多少个节点就行。
- 后序遍历,收集信息
- 判断是否是满二叉树
- 如果是满二叉树,收集以下信息:
-
- 此树的节点数
- 整合左树与右树的节点一共有多少个
var countNodes = function(root) {
if(root == null) {
return 0;
}
let leftNode = root.left;
let rightNode = root.right;
let leftDeth = 0;
let rightDeth = 0;
while(leftNode != null) {
leftNode = leftNode.left;
leftDeth++;
}
while(rightNode != null) {
rightNode = rightNode.right;
rightDeth++;
}
if(leftDeth == rightDeth) {
return Math.pow(2, rightDeth + 1) - 1 ;
}
let leftNum = countNodes(root.left);
let rightNum = countNodes(root.right);
return leftNum + rightNum + 1 ;
};