π― PHP Trees β Top 25 Interview Questions
Q1 β Maximum Depth of Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Height = 1 + max(left height, right height); base case null β 0.
Step 2 β Brute force (what NOT to do): BFS counting levels β works but more code.
Step 3 β Optimal insight: Single DFS recursion; return value bubbles up the max depth.
Step 4 β Algorithm:
1. If node null β return 0
2. Recurse left and right
3. Return 1 + max(left, right)
Step 5 β Edge cases: Empty tree β 0; single node β 1.
function maxDepth(?TreeNode $root): int {
if ($root === null) return 0;
return 1 + max(maxDepth($root->left), maxDepth($root->right));
}
Time: O(n) | Space: O(h)
Q2 β Invert Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Swap left/right children recursively at every node.
Step 2 β Brute force (what NOT to do): Rebuild the tree β wasteful.
Step 3 β Optimal insight: Swap children in-place then recurse.
Step 4 β Algorithm:
1. If null β return null
2. Swap left and right
3. Recurse on both children
Step 5 β Edge cases: Null root; single node.
function invertTree(?TreeNode $root): ?TreeNode {
if ($root === null) return null;
[$root->left, $root->right] = [$root->right, $root->left];
invertTree($root->left);
invertTree($root->right);
return $root;
}
Time: O(n) | Space: O(h)
Q3 β Symmetric Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Mirror check β left.left mirrors right.right, left.right mirrors right.left.
Step 2 β Brute force (what NOT to do): Inorder traversal palindrome check β fails for some cases.
Step 3 β Optimal insight: Recursive helper comparing two subtrees as mirrors.
Step 4 β Algorithm:
1. isMirror(left, right): both null β true; one null β false
2. vals equal AND isMirror(l.left, r.right) AND isMirror(l.right, r.left)
Step 5 β Edge cases: Single node β true; root null β true.
function isSymmetric(?TreeNode $root): bool {
return isMirror($root?->left, $root?->right);
}
function isMirror(?TreeNode $l, ?TreeNode $r): bool {
if ($l === null && $r === null) return true;
if ($l === null || $r === null) return false;
return $l->val === $r->val
&& isMirror($l->left, $r->right)
&& isMirror($l->right, $r->left);
}
Time: O(n) | Space: O(h)
Q4 β Path Sum
π§ How to Approach This
Step 1 β Recognize the pattern: Subtract root value at each step; check leaf when remainder = 0.
Step 2 β Brute force (what NOT to do): Enumerate all root-to-leaf paths then sum β O(n log n) space.
Step 3 β Optimal insight: Pass remaining target down; at leaf check if exactly 0 remaining.
Step 4 β Algorithm:
1. If null β false
2. remaining = targetSum - root.val
3. If leaf and remaining == 0 β true
4. Return hasPathSum(left, rem) || hasPathSum(right, rem)
Step 5 β Edge cases: Empty tree; negative values allowed.
function hasPathSum(?TreeNode $root, int $targetSum): bool {
if ($root === null) return false;
$rem = $targetSum - $root->val;
if ($root->left === null && $root->right === null) return $rem === 0;
return hasPathSum($root->left, $rem) || hasPathSum($root->right, $rem);
}
Time: O(n) | Space: O(h)
Q5 β Level Order Traversal
π§ How to Approach This
Step 1 β Recognize the pattern: BFS with level-size tracking.
Step 2 β Brute force (what NOT to do): DFS with level markers β more complex.
Step 3 β Optimal insight: Process queue in batches of current level size.
Step 4 β Algorithm:
1. Init queue with root
2. While queue not empty: capture size, process that many nodes, enqueue children
Step 5 β Edge cases: Empty tree β [].
function levelOrder(?TreeNode $root): array {
if ($root === null) return [];
$result = [];
$queue = [$root];
while (!empty($queue)) {
$size = count($queue);
$level = [];
for ($i = 0; $i < $size; $i++) {
$node = array_shift($queue);
$level[] = $node->val;
if ($node->left) $queue[] = $node->left;
if ($node->right) $queue[] = $node->right;
}
$result[] = $level;
}
return $result;
}
Time: O(n) | Space: O(w)
Q6 β Validate Binary Search Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Every node must be within (min, max) bounds passed down from ancestors.
Step 2 β Brute force (what NOT to do): Inorder check β misses some valid-looking but invalid trees.
Step 3 β Optimal insight: Pass min/max bounds; tighten at each step.
Step 4 β Algorithm:
1. validate(node, min=ββ, max=+β)
2. If val β€ min or val β₯ max β false
3. Recurse left with max=val, right with min=val
Step 5 β Edge cases: Duplicate values; INT_MIN/INT_MAX nodes.
function isValidBST(?TreeNode $root): bool {
return validate($root, PHP_INT_MIN, PHP_INT_MAX);
}
function validate(?TreeNode $node, int $min, int $max): bool {
if ($node === null) return true;
if ($node->val <= $min || $node->val >= $max) return false;
return validate($node->left, $min, $node->val)
&& validate($node->right, $node->val, $max);
}
Time: O(n) | Space: O(h)
Q7 β Lowest Common Ancestor of BST
π§ How to Approach This
Step 1 β Recognize the pattern: In BST, if both p and q < root β LCA in left; both > root β right; else root is LCA.
Step 2 β Brute force (what NOT to do): General LCA without using BST property β O(n).
Step 3 β Optimal insight: BST property narrows direction without visiting all nodes.
Step 4 β Algorithm:
1. If p.val and q.val both < root.val β recurse left
2. If both > root.val β recurse right
3. Else β root is LCA
Step 5 β Edge cases: p or q equals root itself.
function lowestCommonAncestor(TreeNode $root, TreeNode $p, TreeNode $q): TreeNode {
if ($p->val < $root->val && $q->val < $root->val)
return lowestCommonAncestor($root->left, $p, $q);
if ($p->val > $root->val && $q->val > $root->val)
return lowestCommonAncestor($root->right, $p, $q);
return $root;
}
Time: O(h) | Space: O(h)
Q8 β Lowest Common Ancestor of Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Post-order DFS β find p or q in subtrees; if both sides return non-null β current node is LCA.
Step 2 β Brute force (what NOT to do): Store root-to-node paths then find last common β O(n) space.
Step 3 β Optimal insight: Single DFS returning the node when found; LCA is where both sides return non-null.
Step 4 β Algorithm:
1. If null or matches p/q β return node
2. Recurse left and right
3. If both non-null β return root; else return whichever is non-null
Step 5 β Edge cases: p is ancestor of q.
function lcaBinaryTree(?TreeNode $root, TreeNode $p, TreeNode $q): ?TreeNode {
if ($root === null || $root === $p || $root === $q) return $root;
$left = lcaBinaryTree($root->left, $p, $q);
$right = lcaBinaryTree($root->right, $p, $q);
if ($left !== null && $right !== null) return $root;
return $left ?? $right;
}
Time: O(n) | Space: O(h)
Q9 β Binary Tree Right Side View
π§ How to Approach This
Step 1 β Recognize the pattern: BFS β take last node at each level.
Step 2 β Brute force (what NOT to do): DFS with level tracking β works but BFS is more direct.
Step 3 β Optimal insight: During BFS, record the last node in each level batch.
Step 4 β Algorithm:
1. BFS level-order
2. At i === size-1 β append to result
Step 5 β Edge cases: Left-skewed tree shows left nodes; empty tree β [].
function rightSideView(?TreeNode $root): array {
if ($root === null) return [];
$result = [];
$queue = [$root];
while (!empty($queue)) {
$size = count($queue);
for ($i = 0; $i < $size; $i++) {
$node = array_shift($queue);
if ($i === $size - 1) $result[] = $node->val;
if ($node->left) $queue[] = $node->left;
if ($node->right) $queue[] = $node->right;
}
}
return $result;
}
Time: O(n) | Space: O(w)
Q10 β Count Good Nodes in Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Track max value on path from root; node is "good" if val β₯ max.
Step 2 β Brute force (what NOT to do): Store entire path β O(h) space per call.
Step 3 β Optimal insight: Pass running max down; increment counter at each good node.
Step 4 β Algorithm:
1. DFS(node, maxSoFar)
2. If node.val >= maxSoFar β count++; update max
3. Recurse left and right with updated max
Step 5 β Edge cases: Root is always good.
function goodNodes(?TreeNode $root): int {
return dfsGood($root, PHP_INT_MIN);
}
function dfsGood(?TreeNode $node, int $maxSoFar): int {
if ($node === null) return 0;
$good = ($node->val >= $maxSoFar) ? 1 : 0;
$max = max($maxSoFar, $node->val);
return $good + dfsGood($node->left, $max) + dfsGood($node->right, $max);
}
Time: O(n) | Space: O(h)
Q11 β Kth Smallest in BST
π§ How to Approach This
Step 1 β Recognize the pattern: Inorder traversal of BST gives sorted order; stop at kth element.
Step 2 β Brute force (what NOT to do): Collect all inorder values then index β O(n) space.
Step 3 β Optimal insight: Iterative inorder with early exit when counter hits k.
Step 4 β Algorithm:
1. Iterative inorder with stack
2. Decrement k on each pop; when k === 0 β return value
Step 5 β Edge cases: k = 1 (minimum); k = n (maximum).
function kthSmallest(?TreeNode $root, int $k): int {
$stack = [];
$curr = $root;
while ($curr !== null || !empty($stack)) {
while ($curr !== null) { $stack[] = $curr; $curr = $curr->left; }
$curr = array_pop($stack);
if (--$k === 0) return $curr->val;
$curr = $curr->right;
}
return -1;
}
Time: O(h + k) | Space: O(h)
Q12 β Binary Tree Maximum Path Sum
π§ How to Approach This
Step 1 β Recognize the pattern: At each node, max path through it = node + max(0, left gain) + max(0, right gain).
Step 2 β Brute force (what NOT to do): Try all pairs of nodes as endpoints β O(nΒ²).
Step 3 β Optimal insight: Post-order DFS; track global max; return only one side (left or right) to parent.
Step 4 β Algorithm:
1. gain(node) = node.val + max(0, gain(left)) + max(0, gain(right)) β update global max
2. Return node.val + max(0, max(gain(left), gain(right)))
Step 5 β Edge cases: All negative values; single node.
function maxPathSum(?TreeNode $root): int {
$max = PHP_INT_MIN;
$gain = function(?TreeNode $node) use (&$gain, &$max): int {
if ($node === null) return 0;
$l = max(0, $gain($node->left));
$r = max(0, $gain($node->right));
$max = max($max, $node->val + $l + $r);
return $node->val + max($l, $r);
};
$gain($root);
return $max;
}
Time: O(n) | Space: O(h)
Q13 β Serialize and Deserialize Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Preorder DFS + null markers for structure; split and rebuild on deserialize.
Step 2 β Brute force (what NOT to do): Level-order with position indices β complex for sparse trees.
Step 3 β Optimal insight: Preorder "val,#,#" format is self-describing; recurse on token list.
Step 4 β Algorithm:
1. Serialize: DFS preorder, use "#" for null, join with ","
2. Deserialize: split, maintain pointer, recurse
Step 5 β Edge cases: Empty tree β "#"; single node β "1,#,#".
function serialize(?TreeNode $root): string {
if ($root === null) return '#';
return $root->val . ',' . serialize($root->left) . ',' . serialize($root->right);
}
function deserialize(string $data): ?TreeNode {
$tokens = explode(',', $data);
$idx = 0;
$build = function() use (&$build, &$tokens, &$idx): ?TreeNode {
$val = $tokens[$idx++];
if ($val === '#') return null;
$node = new TreeNode((int)$val);
$node->left = $build();
$node->right = $build();
return $node;
};
return $build();
}
Time: O(n) | Space: O(n)
Q14 β Construct Tree from Preorder + Inorder
π§ How to Approach This
Step 1 β Recognize the pattern: Preorder[0] is root; find it in inorder to split left/right subtrees.
Step 2 β Brute force (what NOT to do): Linear scan for root in inorder at each level β O(nΒ²).
Step 3 β Optimal insight: Hash map of inorder indices for O(1) lookup.
Step 4 β Algorithm:
1. Build index map from inorder
2. build(preL, preR, inL, inR): preorder[preL] is root
3. rootIdx = map[root.val]; leftSize = rootIdx - inL
4. Recurse for left and right
Step 5 β Edge cases: Single element; all left or all right children.
function buildTree(array $preorder, array $inorder): ?TreeNode {
$map = array_flip($inorder);
$build = function(int $preL, int $preR, int $inL, int $inR)
use (&$build, &$preorder, &$map): ?TreeNode {
if ($preL > $preR) return null;
$rootVal = $preorder[$preL];
$node = new TreeNode($rootVal);
$rootIdx = $map[$rootVal];
$leftSize = $rootIdx - $inL;
$node->left = $build($preL + 1, $preL + $leftSize, $inL, $rootIdx - 1);
$node->right = $build($preL + $leftSize + 1, $preR, $rootIdx + 1, $inR);
return $node;
};
return $build(0, count($preorder) - 1, 0, count($inorder) - 1);
}
Time: O(n) | Space: O(n)
Q15 β Flatten Binary Tree to Linked List
π§ How to Approach This
Step 1 β Recognize the pattern: Preorder traversal order; right pointer becomes "next", left pointer set to null.
Step 2 β Brute force (what NOT to do): Collect preorder nodes in array, rewire β O(n) space.
Step 3 β Optimal insight: Morris-like: find rightmost of left subtree, attach right subtree there, move left to right.
Step 4 β Algorithm:
1. While root not null:
2. If left: find rightmost of left subtree β attach root.right there β root.right = root.left; root.left = null
3. Advance root = root.right
Step 5 β Edge cases: No left child; single node.
function flatten(?TreeNode $root): void {
$curr = $root;
while ($curr !== null) {
if ($curr->left !== null) {
$prev = $curr->left;
while ($prev->right !== null) $prev = $prev->right;
$prev->right = $curr->right;
$curr->right = $curr->left;
$curr->left = null;
}
$curr = $curr->right;
}
}
Time: O(n) | Space: O(1)
Q16 β Diameter of Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Diameter through a node = height(left) + height(right); track max globally.
Step 2 β Brute force (what NOT to do): Compute height for each node separately β O(nΒ²).
Step 3 β Optimal insight: Combine height computation with diameter tracking in one DFS.
Step 4 β Algorithm:
1. DFS returns height; at each node update max with l+r
2. Return 1 + max(l, r) to parent
Step 5 β Edge cases: Single node β 0; path doesn't have to pass through root.
function diameterOfBinaryTree(?TreeNode $root): int {
$max = 0;
$depth = function(?TreeNode $node) use (&$depth, &$max): int {
if ($node === null) return 0;
$l = $depth($node->left);
$r = $depth($node->right);
$max = max($max, $l + $r);
return 1 + max($l, $r);
};
$depth($root);
return $max;
}
Time: O(n) | Space: O(h)
Q17 β Balanced Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Return -1 as sentinel for unbalanced; otherwise return height.
Step 2 β Brute force (what NOT to do): Compute height separately for each node β O(nΒ²).
Step 3 β Optimal insight: Post-order DFS; propagate -1 upward immediately on imbalance.
Step 4 β Algorithm:
1. check(node): if null return 0
2. left = check(left); if -1 return -1
3. right = check(right); if -1 return -1
4. if |l-r| > 1 return -1; else return 1 + max(l,r)
Step 5 β Edge cases: Empty tree β true.
function isBalanced(?TreeNode $root): bool {
return checkBal($root) !== -1;
}
function checkBal(?TreeNode $node): int {
if ($node === null) return 0;
$l = checkBal($node->left); if ($l === -1) return -1;
$r = checkBal($node->right); if ($r === -1) return -1;
if (abs($l - $r) > 1) return -1;
return 1 + max($l, $r);
}
Time: O(n) | Space: O(h)
Q18 β Sum Root to Leaf Numbers
π§ How to Approach This
Step 1 β Recognize the pattern: Pass accumulated number down; at leaf add to total.
Step 2 β Brute force (what NOT to do): Store all paths as strings, parse β O(nΒ·h) space.
Step 3 β Optimal insight: Pass current number = prev * 10 + node.val; total at leaf.
Step 4 β Algorithm:
1. dfs(node, current = 0): current = current*10 + val
2. If leaf β return current
3. Return dfs(left, current) + dfs(right, current)
Step 5 β Edge cases: Empty tree β 0; single node β its value.
function sumNumbers(?TreeNode $root): int {
$dfs = function(?TreeNode $node, int $curr) use (&$dfs): int {
if ($node === null) return 0;
$curr = $curr * 10 + $node->val;
if ($node->left === null && $node->right === null) return $curr;
return $dfs($node->left, $curr) + $dfs($node->right, $curr);
};
return $dfs($root, 0);
}
Time: O(n) | Space: O(h)
Q19 β Path Sum II (All Paths)
π§ How to Approach This
Step 1 β Recognize the pattern: Backtracking DFS β add node to path, recurse, then remove.
Step 2 β Brute force (what NOT to do): Copy array at each node β O(nΒ·h) space.
Step 3 β Optimal insight: Mutate single path array; push before recurse, pop after.
Step 4 β Algorithm:
1. dfs(node, remaining, path, result)
2. Push node.val; if leaf and remaining==0 β add copy to result
3. Recurse left/right; pop path
Step 5 β Edge cases: No valid paths β return [].
function pathSum(?TreeNode $root, int $targetSum): array {
$result = [];
$dfs = function(?TreeNode $node, int $rem, array &$path) use (&$dfs, &$result): void {
if ($node === null) return;
$path[] = $node->val;
$rem -= $node->val;
if ($node->left === null && $node->right === null && $rem === 0)
$result[] = $path;
$dfs($node->left, $rem, $path);
$dfs($node->right, $rem, $path);
array_pop($path);
};
$path = [];
$dfs($root, $targetSum, $path);
return $result;
}
Time: O(nΒ·h) | Space: O(nΒ·h)
Q20 β Convert Sorted Array to BST
π§ How to Approach This
Step 1 β Recognize the pattern: Middle element becomes root β guarantees balance; recurse on halves.
Step 2 β Brute force (what NOT to do): Insert elements one by one β O(n log n), potentially unbalanced.
Step 3 β Optimal insight: Divide-and-conquer with mid = (l+r)/2 as root.
Step 4 β Algorithm:
1. build(l, r): if l > r return null
2. mid = (l + r) >> 1; create node
3. left = build(l, mid-1); right = build(mid+1, r)
Step 5 β Edge cases: Empty array β null; single element β leaf.
function sortedArrayToBST(array $nums): ?TreeNode {
$build = function(int $l, int $r) use (&$build, &$nums): ?TreeNode {
if ($l > $r) return null;
$mid = ($l + $r) >> 1;
$node = new TreeNode($nums[$mid]);
$node->left = $build($l, $mid - 1);
$node->right = $build($mid + 1, $r);
return $node;
};
return $build(0, count($nums) - 1);
}
Time: O(n) | Space: O(log n)
Q21 β Binary Tree Zigzag Level Order
π§ How to Approach This
Step 1 β Recognize the pattern: BFS level-order; alternate direction each level.
Step 2 β Brute force (what NOT to do): Two separate queues for odd/even levels β complex.
Step 3 β Optimal insight: BFS + toggle flag; array_reverse on odd levels.
Step 4 β Algorithm:
1. BFS with level batch
2. Toggle leftToRight; if false β array_reverse(level)
Step 5 β Edge cases: Single node β no reversal needed.
function zigzagLevelOrder(?TreeNode $root): array {
if ($root === null) return [];
$result = []; $queue = [$root]; $ltr = true;
while (!empty($queue)) {
$size = count($queue); $level = [];
for ($i = 0; $i < $size; $i++) {
$n = array_shift($queue);
$level[] = $n->val;
if ($n->left) $queue[] = $n->left;
if ($n->right) $queue[] = $n->right;
}
$result[] = $ltr ? $level : array_reverse($level);
$ltr = !$ltr;
}
return $result;
}
Time: O(n) | Space: O(w)
Q22 β Delete Node in BST
π§ How to Approach This
Step 1 β Recognize the pattern: Three cases: leaf, one child, two children (replace with inorder successor).
Step 2 β Brute force (what NOT to do): Rebuild BST from scratch β O(n).
Step 3 β Optimal insight: Recurse to find node; on deletion with two children, replace val with inorder successor val then delete successor.
Step 4 β Algorithm:
1. If key < root.val β recurse left; if key > root.val β recurse right
2. Found: leaf β null; one child β return that child
3. Two children: find leftmost of right subtree (min), replace val, delete that node
Step 5 β Edge cases: Key not in tree; root deletion.
function deleteNode(?TreeNode $root, int $key): ?TreeNode {
if ($root === null) return null;
if ($key < $root->val) $root->left = deleteNode($root->left, $key);
else if ($key > $root->val) $root->right = deleteNode($root->right, $key);
else {
if ($root->left === null) return $root->right;
if ($root->right === null) return $root->left;
$succ = $root->right;
while ($succ->left !== null) $succ = $succ->left;
$root->val = $succ->val;
$root->right = deleteNode($root->right, $succ->val);
}
return $root;
}
Time: O(h) | Space: O(h)
Q23 β Binary Tree Level Order Bottom-Up
π§ How to Approach This
Step 1 β Recognize the pattern: Standard BFS level-order, then reverse the result array.
Step 2 β Brute force (what NOT to do): DFS with depth tracking and sort β more complex.
Step 3 β Optimal insight: BFS + array_reverse at the end.
Step 4 β Algorithm:
1. Standard level-order BFS into result
2. Return array_reverse(result)
Step 5 β Edge cases: Empty tree β [].
function levelOrderBottom(?TreeNode $root): array {
if ($root === null) return [];
$result = []; $queue = [$root];
while (!empty($queue)) {
$size = count($queue); $level = [];
for ($i = 0; $i < $size; $i++) {
$n = array_shift($queue);
$level[] = $n->val;
if ($n->left) $queue[] = $n->left;
if ($n->right) $queue[] = $n->right;
}
$result[] = $level;
}
return array_reverse($result);
}
Time: O(n) | Space: O(w)
Q24 β Recover Binary Search Tree
π§ How to Approach This
Step 1 β Recognize the pattern: Inorder traversal of BST is sorted; exactly two nodes are swapped β find them.
Step 2 β Brute force (what NOT to do): Collect all nodes, sort, reinsert β O(n log n).
Step 3 β Optimal insight: Inorder traversal tracking
prev; first inversion = first bad node; second inversion = second bad node.Step 4 β Algorithm:
1. Inorder DFS tracking prev
2. First violation: first = prev, second = curr
3. Subsequent violation: update second only
4. Swap first.val and second.val
Step 5 β Edge cases: Adjacent nodes swapped (only one inversion visible).
function recoverTree(?TreeNode $root): void {
$first = $second = $prev = null;
$inorder = function(?TreeNode $node) use (&$inorder, &$first, &$second, &$prev): void {
if ($node === null) return;
$inorder($node->left);
if ($prev !== null && $prev->val > $node->val) {
if ($first === null) $first = $prev;
$second = $node;
}
$prev = $node;
$inorder($node->right);
};
$inorder($root);
[$first->val, $second->val] = [$second->val, $first->val];
}
Time: O(n) | Space: O(h)
Q25 β Maximum Width of Binary Tree
π§ How to Approach This
Step 1 β Recognize the pattern: BFS with position indices; width = rightmost β leftmost + 1 at each level.
Step 2 β Brute force (what NOT to do): Track null nodes in queue β exponential space for sparse trees.
Step 3 β Optimal insight: Index nodes as in a heap (left=2i+1, right=2i+2); normalize per level to prevent overflow.
Step 4 β Algorithm:
1. BFS queue of [node, index] pairs
2. Per level: width = last.index β first.index + 1
3. Normalize by subtracting level's first index
Step 5 β Edge cases: Single node per level β width 1; highly unbalanced trees.
function widthOfBinaryTree(?TreeNode $root): int {
if ($root === null) return 0;
$maxWidth = 0;
$queue = [[$root, 0]];
while (!empty($queue)) {
$size = count($queue);
$offset = $queue[0][1];
$first = $last = 0;
$nextQ = [];
for ($i = 0; $i < $size; $i++) {
[$node, $idx] = $queue[$i];
$idx -= $offset;
if ($i === 0) $first = $idx;
if ($i === $size-1) $last = $idx;
if ($node->left) $nextQ[] = [$node->left, 2 * $idx];
if ($node->right) $nextQ[] = [$node->right, 2 * $idx + 1];
}
$maxWidth = max($maxWidth, $last - $first + 1);
$queue = $nextQ;
}
return $maxWidth;
}
Time: O(n) | Space: O(w)