The diameter of a binary tree is defined as the length of the longest path between any two nodes within the tree. The path does not necessarily have to pass through the root.
The length of a path between two nodes in a binary tree is the number of edges between the nodes. Note that the path can not include the same node twice.
Given the root of a binary tree root, return the diameter of the tree.
Example 1:
Input: root = [1,null,2,3,4,5]
Output: 3Explanation: 3 is the length of the path [1,2,3,5] or [5,3,2,4].
Example 2:
Input: root = [1,2,3]
Output: 2Constraints:
1 <= number of nodes in the tree <= 100-100 <= Node.val <= 100
You should aim for a solution with O(n) time and O(n) space, where n is the number of nodes in the tree.
The diameter of a binary tree is the maximum among the sums of the left height and right height of the nodes in the tree. Why?
Because the diameter of a binary tree is defined as the longest path between any two nodes in the tree. The path may or may not pass through the root. For any given node, the longest path that passes through it is the sum of the height of its left subtree and the height of its right subtree.
A brute force solution would be to go through every node in the tree and compute its left height and right height, returning the maximum diameter found. This would be an O(n^2) solution. Can you think of a better way? Maybe we can compute the diameter as we calculate the height of the tree? Think about what information you need from each subtree during a single traversal.
We can use the Depth First Search (DFS) algorithm to calculate the height of the tree. At each node, the subtrees return their respective heights (leftHeight and rightHeight). Then we calculate the diameter at that node as d = leftHeight + rightHeight. We use a global variable to update the maximum diameter as needed during the traversal.
For any node in a tree, the longest path that goes through it is:
So to find the tree’s diameter, we check this value for every node.
We also compare it with the best diameter found in the left and right subtrees.
0.leftHeight + rightHeight.# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
leftHeight = self.maxHeight(root.left)
rightHeight = self.maxHeight(root.right)
diameter = leftHeight + rightHeight
sub = max(self.diameterOfBinaryTree(root.left),
self.diameterOfBinaryTree(root.right))
return max(diameter, sub)
def maxHeight(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
return 1 + max(self.maxHeight(root.left), self.maxHeight(root.right))The diameter of a binary tree is the longest path between any two nodes.
This path must go through some node, and at that node the path length is:
So while doing a DFS to compute heights, we can simultaneously track the
maximum left + right seen so far.
This gives the diameter in one pass without recomputing heights.
left height.right height.left + right.1 + max(left, right).This gives an O(n) time solution with a single DFS traversal.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
res = 0
def dfs(root):
nonlocal res
if not root:
return 0
left = dfs(root.left)
right = dfs(root.right)
res = max(res, left + right)
return 1 + max(left, right)
dfs(root)
return resWhere is the number of nodes in the tree and is the height of the tree.
Recursive DFS is the easiest way to compute diameter, but it uses the call stack.
We can simulate the same behavior iteratively using our own stack.
We perform a post-order traversal:
For each node, we store in a map:
After both children are processed, we can compute:
1 + max(leftHeight, rightHeight)max(leftHeight + rightHeight, leftDiameter, rightDiameter)This means every node is processed exactly once.
(height, diameter) for each visited node.height = 1 + max(leftHeight, rightHeight)
diameter = max(leftHeight + rightHeight, leftDiameter, rightDiameter)# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
stack = [root]
mp = {None: (0, 0)}
while stack:
node = stack[-1]
if node.left and node.left not in mp:
stack.append(node.left)
elif node.right and node.right not in mp:
stack.append(node.right)
else:
node = stack.pop()
leftHeight, leftDiameter = mp[node.left]
rightHeight, rightDiameter = mp[node.right]
mp[node] = (1 + max(leftHeight, rightHeight),
max(leftHeight + rightHeight, leftDiameter, rightDiameter))
return mp[root][1]