解题思路
首先,容易得出,所求直径两端的节点一定为叶子节点。这一点用反证法即可证明,假设直径端点为一个非叶子节点,那么他的子节点一定是一个更优端点。
根据题意,在计算直径上溯时,一定会出现唯一的最浅节点。由于题目特意说明了最浅节点并不一定是根节点,所以理论上二叉树中所有节点都可以作为这个最浅节点。(即便是叶节点也可以认为它有2个地址为nullptr的子节点)假如给定一个确定的最浅节点,那么存在唯一“直径”,即存在唯一“一个叶节点经过该最浅节点再到另一个叶节点的路径和的最大值”。也就是说,只要计算出二叉树中所有的节点作为“最浅节点”的“直径”,求该集合中的最大值即可。
到这里其实就可以发现,求解一个父节点的“直径”,其子问题是求解这个父节点的子节点的“直径”,因此这道题可以用动态规划的思想解决,再结合递归和二叉树前序遍历,具体步骤如下:
int ans = 0;
int depth(TreeNode* root) //返回值为节点与最深节点深度之差
{
if(root == nullptr) //如果到达边界
return 0; //返回与最深节点之差为0
int L = findRoot(root->left); //求当前节点与左路径下最深节点距离差
int R = findRoot(root->right); //求当前节点与右路径下最深节点距离差
ans = max(L + R, ans); //求当前节点直径长度
return max(L, R) + 1; //返回当前节点深度
}
完整代码
class Solution
{
int ans = 0;
int depth(TreeNode* root)
{
if(root == nullptr)
return 0;
int L = findRoot(root->left);
int R = findRoot(root->right);
ans = max(L + R, ans);
return max(L, R) + 1;
}
public:
int diameterOfBinaryTree(TreeNode* root)
{
if(root->left == nullptr && root->right == nullptr)
return 0;
ans = depth(root);
return ans;
}
};