104. 二叉树的最大深度|111. 二叉树的最小深度|222. 完全二叉树的节点个数

题目

力扣

思路

迭代法

从题目可知,其实二叉树的深度和二叉树的层数是一样的。

那么,就可以在二叉树的层序遍历时,遍历每层时用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. 后序遍历,收集左右子树信息,之后再整合
  2. 收集以下信息:
    1. 左子树-有几层
    2. 右子树-有几层
  1. 在左子树、右子树中挑层数更多的,加上根节点本身,加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. 后序遍历,收集左子树和右子树的信息
  2. 收集以下信息:
    1. 左子树-深度
    2. 右子树-深度
  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;
};

普通二叉树的节点个数

  1. 后序遍历,收集信息
  2. 收集以下信息:
    1. 左子树-有多少个节点
    2. 右子树-有多少个节点
  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为二叉树的高度)。

也就是说,通过递归,把完全二叉树剪成满二叉树,然后用公式计算有多少个节点就行。

  1. 后序遍历,收集信息
  2. 判断是否是满二叉树
  3. 如果是满二叉树,收集以下信息:
    1. 此树的节点数
  1. 整合左树与右树的节点一共有多少个
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 ;

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值