leetcode 刷题记录 day16

  • 104.二叉树的最大深度
    思路】此题用后序遍历求解最简单。因为子节点到根节点的高度就是二叉树的最大深度。计算子节点的高度,再把高度返回给父节点。如此往复,就可以得到根节点的左右子树的高度,比较后取较大值 + 1 即是最大深度。
    层级遍历求最大深度时,每次重新计算队列的长度时,即为遍历新的一层的开始,所以取到队列长度之后 depth 自增 1 就是二叉树的最大深度。

    // 递归
    var maxDepth = function(root) {
      // 二叉树根节点的高度就是二叉树的最大深度
      const getDepth = node => {
        if (!node) return 0;
        let leftDepth =  getDepth(node.left);
        let rightDepth = getDepth(node.right);
    
        return Math.max(leftDepth, rightDepth) + 1;
      }
    
      return getDepth(root);
    };
    
    // 层级遍历:
    const maxDepth = root => {
     if (!root) return 0;
    
     let queue = [root], depth = 0;
     while (queue.length) {
       let size = queue.length;
       depth++;
       while (size--) {
         let node = queue.shift();
         node.left && queue.push(node.left);
         node.right && queue.push(node.right);
       }
     }
     return depth;
    }
    
  • 559. n叉树的最大深度
    思路】N 叉树不能用左右子节点的方法遍历,只有 children 节点。所以遍历二叉树用 for 循环,每次遍历一个根节点到子节点的距离,比较现在的根节点到子节点的距离和上一次距离的深度,取每次的最大值,最后得到的 depth 即为最大深度。
    N 叉树层序遍历方法同二叉树的层序遍历方法。

    // 递归法
    var maxDepth = function(root) {
        if(!root) return 0
        let depth = 0
        for(let node of root.children) {
            depth = Math.max(depth, maxDepth(node))
        }
        return depth + 1
    }
    
    // 迭代解法:
    const maxDepth = root => {
     if (!root) return 0;
    
     let queue = [root], count = 0;
     while (queue.length) {
       let size = queue.length; 
       count++;  // 每重新记录一次队列长度,证明又是新的一层,记录层数
    
       while (size--) {
         let node = queue.shift();
         for (let item of node.children) {
           item && queue.push(item);
         }
       }
     }
     return count;
    }
    
  • 111.二叉树的最小深度
    思路】求二叉树最小深度时,不能像求最大深度一样,直接比较根节点的左右子树深度,因为会存在可能一遍子树为 NULL 的情况,即没有左子树 or 没有右子树。所以要分情况讨论返回的值是什么:

    1. 左子树为空,右子树不为空:返回右子树的递归结果;
    2. 左子树不为空,右子树为空:返沪左子树递归结果;
    3. 左右子树都为空:返回 1(即只有根节点);
    4. 根节点为空:返回 0;
    5. 比较左右子树的深度返回较小值
      【层序遍历求解】最小深度的特点是遇到第一个左右节点都为 null 的子节点就直接返回深度。
    // 递归
    var minDepth = function(root) {
      const getDepth = node => {
        if (!node) return 0; // 二叉树为空
        if (!node.left && !node.right) return 1;  // 只有根节点
        if (!node.left) return getDepth(node.right) + 1;  // 没有左子树,只遍历右子树即可
        if (!node.right) return getDepth(node.left) + 1;  // 没有右子树,只遍历左子树即可
        return Math.min(getDepth(node.left), getDepth(node.right)) + 1;  // 左右子树都有的情况下返回最小的高度
      }
    
      return getDepth(root);
    };
    
    // 迭代法:
    const minDepth = root => {
      if (!root) return 0;
    
      let queue = [root], count = 0;
      while (true) {
        let size = queue.length;
        count++;
        while (size--) {
          let node = queue.shift();
          if (!node.left && !node.right) return count;  // 没有左右节点就证明此时的 node 节点为子节点
          node.left && queue.push(node.left);
          node.right && queue.push(node.right);
        }
      }
    }
    
  • 222.完全二叉树的节点个数
    思路

    • 利用满二叉树性质求解:满二叉树的节点个数计算公式是 2<<k + 1,而满二叉树一定是完全二叉树。所以我们可以先判断是否为满二叉树,是的话用公式求解,否则正常递归。如何判断根节点的子树是满二叉树呢?完全二叉树的特点是最后一层节点必须是从左至右顺序,中间不能有空节点,而满二叉树是一个节点必须左右子节点全有或者全没有(如下图)。
    • 递归解法:正常遍历所有节点计数。
    • 层级遍历:队列每次循环的长度就是每一层节点的个数,累加队列长度 size 即可得到总节点个数。
      请添加图片描述
// 利用满二叉树性质
var countNodes = function(root) {
  // 考虑两种情况:子树是否是满二叉树
  const getCounts = node => {
    if (!node) return 0;

    let leftNode = node.left, rightNode = node.right, leftCount = 0, rightCount = 0;
    
    while (leftNode) {
      leftNode = leftNode.left;
      leftCount++;
    }

    while (rightNode) {
      rightNode = rightNode.right;
      rightCount++;
    }
    if (leftCount === rightCount) return Math.pow(2,leftCount + 1) - 1;;  // 满二叉树直接返回满二叉树计算节点公式
    
    return getCounts(node.left) + getCounts(node.right) + 1;
  }

  return getCounts(root);
};

// 递归解法
const countNodes = root => {
  if (!root) return 0;

  let leftDepth = countNodes(root.left);
  let rightDepth = countNodes(root.right);

  return leftDepth + rightDepth + 1;
}

// 层级遍历:
const countNodes = root => {
  if (!root) return 0;

  let queue = [root], count = 0;
  while (queue.length) {
    let size = queue.length;
    count += size;
    while (size--) {
      let node = queue.shift();
      node.left && queue.push(node.left);
      node.right && queue.push(node.right);
    }
  }
  return count;
}

参考代码随想录:https://www.programmercarl.com/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值