【算法-LeetCode】543. 二叉树的直径(二叉树;递归;后序遍历;二叉树的深度)

543. 二叉树的直径 - 力扣(LeetCode)

文章起笔:2021年11月4日19:24:55

问题描述及示例

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点

示例 :
给定二叉树

      1
     / \
    2   3
   / \     
  4   5    

返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

注意:
两结点之间的路径长度是以它们之间边的数目表示

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/diameter-of-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解

首先根据【提示】里面的信息,再结合示例,其实我们可以发现一棵树的直径就是以某个节点(假设为 node)为根节点的左右子树的深度(注意不是高度,这两者的概念稍有差别)之和。而 node 可以不必要是整棵二叉树的根节点 root

于是乎,求直径的问题就转化为求二叉树的最大深度的问题,并且在求最大深度的同时对直径的取值做实时的更新。

而此前我已经写过一篇求二叉树最大深度的题解可做参考:

参考:【算法-LeetCode】104. 二叉树的最大深度(二叉树;递归后序)_赖念安的博客-CSDN博客

本题就是在上面这道题的基础上做的一点改动,基本结构还是不变,仍然采用后序遍历。

注意,题目中说了【直径可能穿过也可能不穿过根结点】,比如下面这种情况:
【算法-LeetCode】543. 二叉树的直径(二叉树;递归;后序遍历;二叉树的深度)_第1张图片

直径不经过根节点的情况

所以,不能只求根节点的左右子树高度,然后做加法。

/**
 * 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 diameterOfBinaryTree = function(root) {
  // 初始化直径为0
  let diameter = 0;
  // 获取整棵二叉树的深度,在这个过程中不断地对diameter的值做更新,使所得直径的值保持最大
  getDepth(root);
  // 最后将获得的最大直径作为最后结果返回
  return diameter;

  // getDepth用于获取以二叉树中的某个节点node为根节点的子树的深度
  // 这里的逻辑和上面我提到的博客中的逻辑是一样的,这里就不再赘述了
  function getDepth(node) {
    if(!node) {
      return 0;
    }
    let rightDepth = getDepth(node.right);
    let leftDepth = getDepth(node.left);
    // 在获取了node的左右子树的深度后,在返回node子树的深度之前,
    // 顺便更新diameter的值为最新的最大值,这也是和之前那道题唯一不同的地方
    // 注意,这里子树的深度刚好就是我们要的节点之间的边的条数,所以直接相加就好了
    diameter = Math.max(diameter, rightDepth + leftDepth);
    // 最后不要忘了getDepth函数的本职工作是获取node子树的深度,所以要返回相应的值
    return Math.max(rightDepth, leftDepth) + 1;
  }
};


提交记录
执行结果:通过
104 / 104 个通过测试用例
执行用时:84 ms, 在所有 JavaScript 提交中击败了45.55%的用户
内存消耗:41.5 MB, 在所有 JavaScript 提交中击败了48.11%的用户
时间:2021/11/04 19:20

getDepth(node) 函数的本意是求 node 子树的深度,但是在本题中,我们只是利用了它的遍历过程,在这个过程中按照直径的定义来不断更新直径的值。

注意在这类的递归中,需要将当前层的结果作为返回值返回到上一层。所以理解好递归的调用过程是非常关键的。但是由于递归的抽象性,并且在递归过程中还涉及对作用域的理解,所以这种时候最好还是在浏览器的开发者工具中通过逐步调试来观察整个递归过程中变量和调用栈的变化

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

【更新结束】

更新:2021年11月4日19:19:59

参考:二叉树的直径 - 二叉树的直径 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年11月4日19:19:38
参考:【算法-LeetCode】104. 二叉树的最大深度(二叉树;递归后序)_赖念安的博客-CSDN博客

你可能感兴趣的:(LeetCode,leetcode,javascript,二叉树,后序遍历,递归法)