题目来源
题目描述
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int diameterOfBinaryTree(TreeNode* root) {
}
};
题目解析
递归套路
对于以root为头结点的二叉树,它的最大距离的可能性有两类:经过root,不经过root
- 最大路径不经过root:对于root,需要知道它左子树的最大直径、右子树的最大直径分别是多少
- 最大直径经过root:此时, 二叉树的直径 = 左孩子的边 + 右孩子的边 = 左孩子的高度 + 右孩子的高度
也就是每次我们都需要从root的子树中得到两个信息:
- 你的最大直径是多少?
- 你的高度
因此我们定义一个辅助类Info:
然后递归求解:
- 当root为NULL时,返回Info(0, 0);
- 当root不为NULL时:
- h r o o t = m a x ( h l , h r ) + 1 h_{root} = max(h_{l}, h_r) + 1 hroot=max(hl,hr)+1
- 对于当前节点的
d
r
d_r
dr,有三种可能:
- 如果经过当前节点,此时直径是: d r o o t = h l + h r d_{root} = h_{l} + h_r droot=hl+hr
- 如果不经过当前节点,那么可能是左节点的最大距离 d r d_r dr,也可能是右节点的最大距离 d l d_l dl
- 从上面三个最大距离中选出一个最大的返回即可
最终代码:
class Solution {
struct Info{
int maxDiameter;
int height;
Info(int height, int maxDiameter) : height(height), maxDiameter(maxDiameter){
}
};
std::shared_ptr<Info> process(TreeNode* root){
if(root == nullptr){
return std::make_shared<Info>(0, 0);
}
auto left = process(root->left);
auto right = process(root->right);
int height = std::max(left->height, right->height) + 1;
int maxDiameter =
std::max(
(left->height + right->height),
std::max(left->maxDiameter, right->maxDiameter)
);
return std::make_shared<Info>(height, maxDiameter);
}
public:
int diameterOfBinaryTree(TreeNode* root) {
if(root == nullptr){
return 0;
}
return process(root)->maxDiameter;
}
};
递归
class Solution {
int ans = 0;
int helper(TreeNode* root){
if (root == nullptr){
return 0;
}
int left = helper(root->left);
int right = helper(root->right);
ans = std::max(ans, left + right);
return std::max(left, right) + 1; // 孩子多的个数 + 当前节点 = 最大节点个数
}
public:
int diameterOfBinaryTree(TreeNode* root) {
helper(root);
return ans;
}
};