js算法题解(第34天)---leetcode 543. 二叉树的直径

371 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

前言:

每天一道算法题目,死磕算法

题目

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

示例 : 给定二叉树

      1
     / \
    2   3
   / \     
  4   5    

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

分析

Q:什么是二叉树直径?
A:所谓二叉树直接就是中两片叶子之间最长路径上的节点数。

图片.png 上图红色数字即为每个节点为顶点的路径长度,所有节点的路径长度的最大值即为二叉树的最大路径长度

一棵二叉树的直径长度,其实可以将其看为左右子树的最大深度之和。

如果真是这样的话,那么题目太简单了,可题目中有一个大坑

这条路径可能穿过也可能不穿过根结点。

意思就是有可能根节点的左右子树的直径不是最大的

图片.png

就像上面这种情况一样,根节点的树的直径不是最大的

所以我们的思路如下

  1. 定义一个变量,记录所有节点的直径
  2. 遍历二叉树,计算所有结点的直径
  3. 通过Math.max得到最大的直径

首先我们复习一下,深度遍历获取树高度的模板

const dfs = function(root){
         // 递归结束条件
        if(!root){
            return 0;
        }
        let left = dfs(root.left);
        let right = dfs(root.right);
        // 逆想思维求高度
        return Math.max(left,right)+1;
    }

所以我们的题解如下

题解

var diameterOfBinaryTree = function(root) {
    // 返回的结果
    let result = 0;
    const dfs = function(root){
         // 递归结束条件
        if(!root){
            return 0;
        }
        let left = dfs(root.left);
        let right = dfs(root.right);
        // left+right就是当前节点的直径
        // result是遍历的以前节点的最大值
        result = Math.max(result,left+right);
        // 逆想思维求高度
        return Math.max(left,right)+1;
    }
    // 进行深度优先遍历
    dfs(root)
    return result;
};
  • 时间复杂度:O(n),其中n为二叉树的节点个数。因为每个节点都会处理一次
  • 空间复杂度:O(Height),其中 Height 为二叉树的高度。由于递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,而递归的深度显然为二叉树的高度,并且每次递归调用的函数里又只用了常数个变量,所以所需空间复杂度为 O(Height) 。

参考