树的深度
递归:
- 确定遍历的参数和返回值
- 确定递归边界
- 确定单层的逻辑
树的最大深度就是根节点的高度,使用后序遍历从叶子结点开始,从叶子结点往根节点走,使用后序遍历就可以实现从子节点到根节点的操作。前序是从上往下走
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var maxDepth = function(node) {
if(!node) return 0;
let leftdepth = maxDepth(node.left)
let rightdepth = maxDepth(node.right)
let curdepth = Math.max(leftdepth, rightdepth);
return curdepth + 1;
};
易错点在于深度指的是从叶子节点到根的距离,如果左右孩子之间,只有一个为空的话,那么这个空子树就会返回0,如果直接Math.min(minDepth(root.left), minDepth(root.right))
,就会取到0,但是这样的取法是不对的,只有左右孩子都为空才能算叶子结点。
但是前面取最大深度就不有有这样的问题,因为取最大深度时取到的一定是叶子结点的值。
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var minDepth = function(root) {
if(!root) return 0;
if(root.left && !root.right) return minDepth(root.left) + 1;
if(!root.left && root.right) return minDepth(root.right) + 1;
return 1 + Math.min(minDepth(root.left), minDepth(root.right));
};
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var countNodes = function(root) {
if(!root) return 0;
//后序遍历,遍历所有结点,没有利用到完全二叉树的特性
return 1 + countNodes(root.right) + countNodes(root.left)
};
利用完全二叉树的特点
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var countNodes = function(root) {
if(!root) return 0;
//预处理,提前处理子完全二叉树
//而判断子完全二叉树的方法,就是看子树左、右臂长是否一致
let l = root.left, r = root.right;
let ldepth = 0, rdepth = 0;
while(l){
l = l.left;
ldepth++;
}
while(r){
r = r.right;
rdepth++;
}
//这里必须加一,因为我们计算的是以当前root为根的子树的个数,但我们取的时候是从l = root.left开始取的
//即整个子树的高度实际上是ldepth + 1,这个子树的左子树高度是ldepth + 1,右子树是rdepth + 1
if(ldepth == rdepth) return 2 ** (ldepth + 1) - 1;
return 1 + countNodes(root.left) + countNodes(root.right);
};