Checking the height of a binary tree is essential when we want to determine if it is balanced.
AVL trees are a category of binary search trees that are always balanced to ensure an O(log n) runtime for search, insertion, and deletion operations. When inserting into or deleting from an AVL tree, we must calculate the balance factor of the nodes and rebalance the tree using rotations whenever an imbalance occurs.
During this process, checking whether the tree is balanced in a single pass—rather than recomputing heights repeatedly—is the most efficient way to do it.
We can achieve this by using -1 as a sentinel value for a cleaner, O(n) implementation:
- Returning
-1indicates that a subtree is already unbalanced. - Returning a non-negative integer conveys the actual height of the subtree, which can then be used by parent nodes to calculate their own balance factors.
The Code Implementation
Here is how this single-pass height checking and balance detection logic looks in Python:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def check_height(root: TreeNode) -> int:
"""
Returns the height of the tree if it is balanced.
Returns -1 if the tree (or any subtree) is unbalanced.
"""
if not root:
return 0 # An empty tree has a height of 0 and is balanced
# Check left subtree
left_height = check_height(root.left)
if left_height == -1:
return -1 # Left subtree is not balanced
# Check right subtree
right_height = check_height(root.right)
if right_height == -1:
return -1 # Right subtree is not balanced
# Check if current node is balanced
if abs(left_height - right_height) > 1:
return -1 # Current node is not balanced
# Return height of the current subtree
return 1 + max(left_height, right_height)
def is_balanced(root: TreeNode) -> bool:
return check_height(root) != -1
Unit Test Suite
Key Takeaways
- Avoid Recomputation: A naive approach calculates height separately for every node, leading to an O(n²) time complexity: To find the height of any given node, you must traverse down all of its descendant nodes to the lowest leaf.
- Early Termination: By bubbling up
-1as soon as an imbalance is detected, the algorithm short-circuits early without wasting computation on the rest of the tree. - Optimal Time Complexity: This sentinel pattern checks balance and computes heights simultaneously in a single bottom-up post-order traversal, keeping time complexity down to O(n).
.jpg)
Comments
Post a Comment