题目描述
计算一棵二叉树的直径。
对于直径的定义:二叉树中任意两个节点之间的最长路径,这个路径可能不通过根节点root
示例:如下二叉树的直径是3, 有两条路径,[4,2,1,3] 或者 [5,2,1,3]
1
/ \
2 3
/ \
4 5
解题思路
因为一向不是太擅长做二叉树的题,所以一开始拿到这题的时候还挺懵的,脑子里的二叉树开始胡乱操作胡乱遍历,一直在想是不是要采用某种遍历方式,一边遍历一边记录下路径长度并且随时替换最大值,越想越乱。
后来顺着遍历这条路想不下去,就清了清脑子开始重新读题,体会示例,发现其实是我想复杂了,这道题目的本质非常清楚简单。
如果我要从根节点出发,寻找一条所谓的“最长路径”的长度,我其实就只是要根节点左子树的最长路径长加上右子树的最长路径长就可以,本质上,其实就是根节点左子树的深度加上右子树的深度。
那么,现在最长路径不一定通过根节点,也就是我要对每个节点都计算它左子树的深度和右子树的深度和,从中找出一个最大的就是了。
所以,一通分析之后发现,这道题目其实就是考你一个二叉树的深度计算。
代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int res = -1;
public int diameterOfBinaryTree(TreeNode root) {
// 对于每个节点,计算左子树深度 + 右子树深度,取最大的那个
if (root == null) {
return 0;
}
getDepth(root);
return res - 1;
}
public int getDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = getDepth(root.left);
int right = getDepth(root.right);
res = Math.max(res, left + right + 1);
return Math.max(left, right) + 1;
}
}
代码中还有一个小细节需要注意,变量res
保存的是最长路径的节点数量,要得到路径长度,返回的时候需要-1
反思总结
一直以来都比较怵二叉树的题目,觉得很复杂,尤其是大部分二叉树操作采用的都是递归的方式,会显得更加复杂。
但今天做这道题(尽管是一道easy题)之后发现,其实二叉树说到底就那么几个操作,各种遍历、计算高度深度等等,只不过在出题的时候会加上很多迷惑性信息,比如这道题,其实本质就是一个深度计算,但题目里出了个直径计算,就会让人觉得复杂。
做题其实最主要的就是透过题面看到题目本质,而本质往往都是一些非常基础的东西。
因此,以后要是做到一眼看过去不会做的题,多读几遍题目,多写几个例子,好好思考一下这道题在考什么。