What if you could instantly know if your tree is balanced without counting every branch twice?
Why Check if Binary Tree is Balanced in DSA Rust?
Imagine you have a family tree drawn on paper. You want to check if the tree looks balanced, meaning no side is much taller than the other. Doing this by measuring each branch by hand is tiring and confusing.
Manually checking each branch's height and comparing takes a lot of time and mistakes happen easily. You might miss some branches or count wrong, making the whole check unreliable.
Using a smart method, you can check the tree's balance by looking at each branch just once, quickly finding if any side is too tall compared to the other. This saves time and avoids errors.
fn height(node: &Option<Box<Node>>) -> i32 {
if node.is_none() { return 0; }
let left_height = height(&node.as_ref().unwrap().left);
let right_height = height(&node.as_ref().unwrap().right);
left_height.max(right_height) + 1
}
// Then check balance by comparing heights separatelyfn check_balance(node: &Option<Box<Node>>) -> (bool, i32) {
if node.is_none() { return (true, 0); }
let (left_balanced, left_height) = check_balance(&node.as_ref().unwrap().left);
let (right_balanced, right_height) = check_balance(&node.as_ref().unwrap().right);
let balanced = left_balanced && right_balanced && (left_height - right_height).abs() <= 1;
(balanced, left_height.max(right_height) + 1)
}This lets you quickly and reliably know if a tree is balanced, which helps keep data organized and fast to search.
When building a phone contact list, a balanced tree ensures you find a contact quickly without waiting long because one side of the list is too long.
Manual height checks are slow and error-prone.
Smart recursive checks combine height and balance in one step.
Balanced trees keep data fast to access and reliable.
Practice
Solution
Step 1: Understand balance condition
A balanced binary tree means for every node, the height difference between its left and right subtrees is at most 1.Step 2: Eliminate incorrect options
All nodes having two children describes a full tree. Equal number of nodes in subtrees does not define balance. Sorted order defines a BST. None match the balance definition.Final Answer:
The height difference between left and right subtrees of every node is at most 1 -> Option AQuick Check:
Balance means height difference ≤ 1 [OK]
- Confusing balanced with complete or full tree
- Thinking balance means equal number of nodes
- Assuming sorted order means balanced
Solution
Step 1: Understand Rust ownership and references
Binary trees are usually represented with Option<Box<TreeNode>>. Passing by reference (&Option<Box<TreeNode>>) avoids moving ownership.Step 2: Analyze the signatures
Passing Option<Box<TreeNode>> moves ownership. Option<TreeNode> is invalid due to infinite size. TreeNode directly ignores None roots. &Option<Box<TreeNode>> correctly borrows the tree.Final Answer:
fn is_balanced(root: &Option<Box<TreeNode>>) -> bool -> Option CQuick Check:
Use reference to Option<Box<TreeNode>> [OK]
- Passing TreeNode directly instead of boxed option
- Not using references causing ownership errors
- Using Option<TreeNode> instead of Option
struct TreeNode {
val: i32,
left: Option,
right: Option,
}
fn height(node: &Option) -> i32 {
match node {
None => 0,
Some(n) => 1 + i32::max(height(&n.left), height(&n.right)),
}
}
fn is_balanced(root: &Option) -> bool {
match root {
None => true,
Some(n) => {
let lh = height(&n.left);
let rh = height(&n.right);
(lh - rh).abs() <= 1 && is_balanced(&n.left) && is_balanced(&n.right)
}
}
}
fn main() {
let tree = Some(Box::new(TreeNode {
val: 1,
left: Some(Box::new(TreeNode {
val: 2,
left: None,
right: None,
})),
right: None,
}));
println!("{}", is_balanced(&tree));
}Solution
Step 1: Analyze tree structure
The tree has root 1, left child 2, and no right child. Left subtree height = 1, right subtree height = 0.Step 2: Check balance condition
Height difference is 1 which is ≤ 1. Both left and right subtrees are leaves or None, so balanced. So overall tree is balanced.Final Answer:
true -> Option AQuick Check:
Height difference ≤ 1 means balanced [OK]
- Assuming missing right child means unbalanced
- Confusing height calculation logic
- Ignoring recursive balance checks
fn is_balanced(root: &Option) -> bool {
if root.is_none() {
return true;
}
let node = root.as_ref().unwrap();
let lh = height(&node.left);
let rh = height(&node.right);
if (lh - rh).abs() > 1 {
return false;
}
is_balanced(&node.left);
is_balanced(&node.right);
true
}Solution
Step 1: Review recursive calls
The recursive calls to is_balanced(&node.left) and is_balanced(&node.right) are made but their results are not used or returned.Step 2: Understand impact
Ignoring recursive results means function always returns true if root is not None and height difference ≤ 1, missing unbalanced deeper nodes.Final Answer:
Missing return of recursive calls results in ignoring their results -> Option DQuick Check:
Return recursive results to propagate balance status [OK]
- Not returning recursive call results
- Assuming unwrap() always safe without check
- Confusing parameter types
Solution
Step 1: Understand repeated height calculation problem
Calculating height separately for each node causes repeated work, increasing time complexity.Step 2: Use combined recursive function
Returning height if balanced or None if unbalanced lets us stop early and avoid repeated height calls.Step 3: Analyze other options
Separate height and balance traversals is less efficient. Global variables introduce unsafe state. Root-only check misses subtree imbalances.Final Answer:
Calculate height and balance in one recursive function returning Option<i32> height or None if unbalanced -> Option BQuick Check:
Combine height and balance check for efficiency [OK]
- Doing separate height and balance traversals
- Using global variables for tree state
- Checking balance only at root
Ready to prove it?
Pass the test and this pattern moves unknown
