LeetCode 543
https://leetcode.cn/problems/diameter-of-binary-tree/description/
难度:简单
树形 DP 中的直径 DP。
链:从子树中的叶子节点到当前节点的路径。把最长链的长度,作为 dfs 的返回值。根据这一定义,空节点的链长是 −1,叶子节点的链长是 0。
直径:等价于由两条(或者一条)链拼成的路径。我们枚举每个 node,假设直径在这里「拐弯」,也就是计算由左右两条从下面的叶子节点到 node 的链的节点值之和,去更新答案的最大值。
直径可能在下面的某个节点拐弯,不一定经过树根 root。
dfs 返回的是链的长度,不是直径的长度。如果返回直径,那么上面与其他的链继续拼接,得到的就不是直径了。
dfs 返回的是当前子树的最大链长(也可以理解为子树的高度),不包含当前节点和其父节点的这条边。
时间复杂度:O(n),其中 n 为二叉树的节点个数。
空间复杂度:O(n)。最坏情况下,二叉树退化成一条链,递归需要 O(n) 的栈空间。
class Solution {
public:
int diameterOfBinaryTree(TreeNode* root) {
int ans = 0;
auto dfs = [&](this auto&& dfs, TreeNode* node) -> int {
if (node == nullptr) {
return -1; // 对于叶子来说,链长就是 -1+1=0
}
int l_len = dfs(node->left) + 1; // 左子树最大链长+1
int r_len = dfs(node->right) + 1; // 右子树最大链长+1
ans = max(ans, l_len + r_len); // 两条链拼成路径
return max(l_len, r_len); // 当前子树最大链长
};
dfs(root);
return ans;
}
};