算法的核心思想是通过递归遍历整棵二叉树,在每个节点处计算它的左右子树的深度,并且利用这些深度来更新最大直径。详细解释如下:
算法思路:
-
递归遍历每个节点:
- 通过递归,从树的最底层(叶子节点)开始向上逐层计算每个节点的左右子树的深度。
- 对于每个节点,递归函数
depth()
会先计算该节点的左子树深度和右子树深度。
-
更新最大直径:
- 对于每个节点,二叉树经过该节点的路径长度就是左子树的深度 + 右子树的深度。
maxDiameter
变量用于记录当前的最大直径。如果当前节点的左右子树深度之和(即路径长度)大于已有的maxDiameter
,就更新maxDiameter
。
-
返回节点的深度:
depth()
函数返回当前节点的深度,这个深度是该节点到其最深叶子节点的距离,具体为:
[
\text{深度} = \max(\text{左子树深度}, \text{右子树深度}) + 1
]- 递归结束时,这个返回值会被用于父节点的递归调用,帮助父节点计算它的深度和直径。
关键点:
- 递归计算深度:每个节点的深度就是左右子树深度中的较大者加1,这个值递归地传递给上一级节点。
- 最大直径更新:直径是在递归过程中不断更新的,通过对每个节点计算它的左右子树深度之和,并与当前最大直径比较,实时更新。
最终结果:
当递归结束时,maxDiameter
中保存的就是整个树的最大直径。
图解:
举例说明,假设我们有以下二叉树:
1
/ \
2 3
/ \
4 5
- 递归先从叶子节点
4
、5
、3
开始,计算它们的深度为1
。 - 节点
2
的左右子树深度分别为1
(左)和1
(右),所以节点2
的深度为2
,并且通过节点2
的路径长度为1 + 1 = 2
,此时更新直径为2
。 - 节点
1
的左右子树深度分别为2
(左)和1
(右),所以节点1
的深度为3
,通过节点1
的路径长度为2 + 1 = 3
,更新直径为3
。
因此,最终直径为3
。
这个算法的时间复杂度是O(N)
,因为我们访问每个节点一次,计算它的深度和更新最大直径。
java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private int maxDiameter = 0;
public int diameterOfBinaryTree(TreeNode root) {
depthoftree(root);
return maxDiameter;
}
private int depthoftree(TreeNode root) {
if(root == null) {
return 0;
}
int leftsubtreedepth = depthoftree(root.left);
int rightsubtreedepth = depthoftree(root.right);
maxDiameter = Math.max(leftsubtreedepth + rightsubtreedepth, maxDiameter);
return Math.max(leftsubtreedepth, rightsubtreedepth) + 1;
}
}