16. Tree#
Problems at a glance#
| LC | Problem | |
|---|---|---|
| 94 | Binary Tree Inorder Traversal | ↗ |
| 144 | Binary Tree Preorder Traversal | ↗ |
| 145 | Binary Tree Postorder Traversal | ↗ |
| 102 | Binary Tree Level Order Traversal | ↗ |
| 103 | Binary Tree Zigzag Level Order Traversal | ↗ |
| 107 | Binary Tree Level Order Traversal II | ↗ |
| 987 | Vertical Order Traversal of a Binary Tree | ↗ |
| 226 | Invert Binary Tree | ↗ |
| 563 | Binary Tree Tilt | ↗ |
| 543 | Diameter of Binary Tree | ↗ |
| 617 | Merge Two Binary Trees | ↗ |
| 111 | Minimum Depth of Binary Tree | ↗ |
| 110 | Balanced Binary Tree | ↗ |
| 104 | Maximum Depth of Binary Tree | ↗ |
| 100 | Same Tree | ↗ |
| 101 | Symmetric Tree | ↗ |
| 700 | Search in a Binary Search Tree | ↗ |
| 653 | Two Sum IV - Input is a BST | ↗ |
| 530 | Minimum Absolute Difference in BST | ↗ |
| 938 | Range Sum of BST | ↗ |
| 450 | Delete Node in a BST | ↗ |
| 669 | Trim a Binary Search Tree | ↗ |
| 701 | Insert into a Binary Search Tree | ↗ |
| 230 | Kth Smallest Element in a BST | ↗ |
| 1305 | All Elements in Two Binary Search Trees | ↗ |
| 173 | Binary Search Tree Iterator | ↗ |
| 1038 | Binary Search Tree to Greater Sum Tree | ↗ |
| 1373 | Maximum Sum BST in Binary Tree | ↗ |
| 257 | Binary Tree Paths | ↗ |
| 112 | Path Sum | ↗ |
| 113 | Path Sum II | ↗ |
| 129 | Sum Root to Leaf Numbers | ↗ |
| 124 | Binary Tree Maximum Path Sum | ↗ |
| 437 | Path Sum III | ↗ |
| 1457 | Pseudo-Palindromic Paths in a Binary Tree | ↗ |
| 105 | Construct Binary Tree from Preorder and Inorder Traversal | ↗ |
| 106 | Construct Binary Tree from Inorder and Postorder Traversal | ↗ |
| 889 | Construct Binary Tree from Preorder and Postorder Traversal | ↗ |
| 108 | Convert Sorted Array to Binary Search Tree | ↗ |
| 1008 | Construct Binary Search Tree from Preorder Traversal | ↗ |
| 199 | Binary Tree Right Side View | ↗ |
| 236 | Lowest Common Ancestor of a Binary Tree | ↗ |
| 235 | Lowest Common Ancestor of a Binary Search Tree | ↗ |
| 1123 | Lowest Common Ancestor of Deepest Leaves | ↗ |
| 1361 | Validate Binary Tree Nodes | ↗ |
| 98 | Validate Binary Search Tree | ↗ |
| 114 | Flatten Binary Tree to Linked List | ↗ |
| 222 | Count Complete Tree Nodes | ↗ |
| 662 | Maximum Width of Binary Tree | ↗ |
| 958 | Check Completeness of a Binary Tree | ↗ |
| 993 | Cousins in Binary Tree | ↗ |
| 1026 | Maximum Difference Between Node and Ancestor | ↗ |
| 1530 | Number of Good Leaf Nodes Pairs | ↗ |
| 865 | Smallest Subtree with all the Deepest Nodes | ↗ |
| 863 | All Nodes Distance K in Binary Tree | ↗ |
| 1379 | Find a Corresponding Node of a Binary Tree in a Clone of That Tree | ↗ |
| 894 | All Possible Full Binary Trees | ↗ |
| 1325 | Delete Leaves With a Given Value | ↗ |
| 1110 | Delete Nodes And Return Forest | ↗ |
| 652 | Find Duplicate Subtrees | ↗ |
| 337 | House Robber III | ↗ |
| 2096 | Step-By-Step Directions From a Binary Tree Node to Another | ↗ |
| 117 | Populating Next Right Pointers in Each Node II | ↗ |
| 979 | Distribute Coins in Binary Tree | ↗ |
| 297 | Serialize and Deserialize Binary Tree | ↗ |
| 968 | Binary Tree Cameras | ↗ |
Traversal#
Problem 1: Binary Tree Inorder Traversal (Leetcode:94)#
Problem Statement
Given the root of a binary tree, return the inorder traversal of its nodes' values.
Example 1:
Input: root = [1,null,2,3]
Output: [1,3,2]
Explanation:
Example 2:
Input: root = [1,2,3,4,5,null,8,null,null,6,7,9]
Output: [4,2,6,5,7,1,3,9,8]
Explanation:
Example 3:
Input: root = []
Output: []
Example 4:
Input: root = [1]
Output: [1]
Constraints:
- The number of nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
Follow up: Recursive solution is trivial, could you do it iteratively?
Code and Explanation
- Inorder order: left subtree → node → right subtree.
- Recursive DFS: Visit left, append current value, then visit right.
- Base case: empty node returns immediately.
Time: O(n) | Space: O(h) recursion stack
- Simulate recursion with an explicit stack.
- Push all left children first; pop, record value, then move to right child.
- Repeat until both stack and current pointer are empty.
Time: O(n) | Space: O(h)
Problem 2: Binary Tree Preorder Traversal (Leetcode:144)#
Problem Statement
Given the root of a binary tree, return the preorder traversal of its nodes' values.
Example 1:
Input: root = [1,null,2,3]
Output: [1,2,3]
Explanation:
Example 2:
Input: root = [1,2,3,4,5,null,8,null,null,6,7,9]
Output: [1,2,4,5,6,7,3,8,9]
Explanation:
Example 3:
Input: root = []
Output: []
Example 4:
Input: root = [1]
Output: [1]
Constraints:
- The number of nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
Follow up: Recursive solution is trivial, could you do it iteratively?
Code and Explanation
- Preorder order: node → left subtree → right subtree.
- Recursive DFS: Append value first, then recurse left and right.
- Base case: empty node returns immediately.
Time: O(n) | Space: O(h) recursion stack
- Push root onto a stack; process nodes in LIFO order.
- Pop, record value, then push right before left so left is processed first.
- Mirrors recursive preorder without call stack overhead.
Time: O(n) | Space: O(h)
Problem 3: Binary Tree Postorder Traversal (Leetcode:145)#
Problem Statement
Given the root of a binary tree, return the postorder traversal of its nodes' values.
Example 1:
Input: root = [1,null,2,3]
Output: [3,2,1]
Explanation:
Example 2:
Input: root = [1,2,3,4,5,null,8,null,null,6,7,9]
Output: [4,6,7,5,2,9,8,3,1]
Explanation:
Example 3:
Input: root = []
Output: []
Example 4:
Input: root = [1]
Output: [1]
Constraints:
- The number of the nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
Follow up: Recursive solution is trivial, could you do it iteratively?
Code and Explanation
- Postorder order: left subtree → right subtree → node.
- Recursive DFS: Recurse left and right before appending the current value.
- Base case: empty node returns immediately.
Time: O(n) | Space: O(h) recursion stack
- Stack 1 processes nodes in modified preorder (root → right → left).
- Stack 2 collects popped nodes; reversing gives left → right → root.
- Avoids the tricky single-stack postorder simulation.
Time: O(n) | Space: O(n)
Problem 4: Binary Tree Level Order Traversal (Leetcode:102)#
Problem Statement
Given the root of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level).
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]
Example 2:
Input: root = [1]
Output: [[1]]
Example 3:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 2000].-1000 <= Node.val <= 1000
Code and Explanation
- BFS with a queue processes nodes level by level.
- Snapshot
len(queue)each iteration to isolate one level. - Enqueue left and right children after recording the current node.
Time: O(n) | Space: O(w) where w = max width
- DFS tracks depth; extend
resultwhen visiting a new level. - Append each node's value to
result[depth]. - Same output as BFS, useful when already using depth-first logic.
Time: O(n) | Space: O(h)
Problem 5: Binary Tree Zigzag Level Order Traversal (Leetcode:103)#
Problem Statement
Given the root of a binary tree, return the zigzag level order traversal of its nodes' values. (i.e., from left to right, then right to left for the next level and alternate between).
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[20,9],[15,7]]
Example 2:
Input: root = [1]
Output: [[1]]
Example 3:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 2000].-100 <= Node.val <= 100
Code and Explanation
- Standard BFS collects each level left to right.
- Toggle direction each level — reverse the list on odd-indexed levels.
- Enqueue children normally; only the output order alternates.
Time: O(n) | Space: O(w)
- Build each level in order using
appendorappendlefton a deque. - Avoids reversing the whole level after collection.
- Same BFS structure; only insertion side changes per level.
Time: O(n) | Space: O(w)
Problem 6: Binary Tree Level Order Traversal II (Leetcode:107)#
Problem Statement
Given the root of a binary tree, return the bottom-up level order traversal of its nodes' values. (i.e., from left to right, level by level from leaf to root).
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[15,7],[9,20],[3]]
Example 2:
Input: root = [1]
Output: [[1]]
Example 3:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 2000].-1000 <= Node.val <= 1000
Code and Explanation
- Run standard level-order BFS top to bottom.
- Reverse the result list to get bottom-up order.
- Simple and readable; one extra O(levels) reversal.
Time: O(n) | Space: O(w)
- Same BFS, but insert each completed level at index 0.
- Builds bottom-up order during traversal without a final reverse.
insert(0, …)costs O(levels) per level — acceptable for interview clarity.
Time: O(n) | Space: O(w)
Problem 7: Vertical Order Traversal of a Binary Tree (Leetcode:987)#
Problem Statement
Given the root of a binary tree, calculate the vertical order traversal of the binary tree.
For each node at position (row, col), its left and right children will be at positions (row + 1, col - 1) and (row + 1, col + 1) respectively. The root of the tree is at (0, 0).
The vertical order traversal of a binary tree is a list of top-to-bottom orderings for each column index starting from the leftmost column and ending on the rightmost column. There may be multiple nodes in the same row and same column. In such a case, sort these nodes by their values.
Return the vertical order traversal of the binary tree.
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
Explanation:
Column -1: Only node 9 is in this column.
Column 0: Nodes 3 and 15 are in this column in that order from top to bottom.
Column 1: Only node 20 is in this column.
Column 2: Only node 7 is in this column.
Example 2:
Input: root = [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
Column -2: Only node 4 is in this column.
Column -1: Only node 2 is in this column.
Column 0: Nodes 1, 5, and 6 are in this column.
1 is at the top, so it comes first.
5 and 6 are at the same position (2, 0), so we order them by their value, 5 before 6.
Column 1: Only node 3 is in this column.
Column 2: Only node 7 is in this column.
Example 3:
Input: root = [1,2,3,4,6,5,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
This case is the exact same as example 2, but with nodes 5 and 6 swapped.
Note that the solution remains the same since 5 and 6 are in the same location and should be ordered by their values.
Constraints:
- The number of nodes in the tree is in the range
[1, 1000].0 <= Node.val <= 1000
Code and Explanation
- BFS assigns each node a
(row, col)coordinate from the root at(0, 0). - Sort by
(col, row, val)— column left-to-right, then top-to-bottom, then value. - Group consecutive equal columns into output lists.
Time: O(n log n) | Space: O(n)
- DFS records
(row, val)tuples in a map keyed by column index. - Sort columns left to right; within each column sort by row then value.
- Equivalent logic to BFS; DFS avoids an explicit queue.
Time: O(n log n) | Space: O(n)
Build Understanding#
Problem 1: Invert Binary Tree (Leetcode:226)#
Problem Statement
Given the root of a binary tree, invert the tree, and return its root.
Example 1:
Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]
Explanation:
Example 2:
Input: root = [2,1,3]
Output: [2,3,1]
Example 3:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
Code and Explanation
- Swap left and right pointers at the current node.
- Recurse on both subtrees to invert the entire tree.
- Base case:
Noneneeds no swapping.
Time: O(n) | Space: O(h)
- BFS queue visits every node level by level.
- Swap children at each node before enqueueing them.
- Avoids recursion depth limits on skewed trees.
Time: O(n) | Space: O(w)
Problem 2: Binary Tree Tilt (Leetcode:563)#
Problem Statement
Given the root of a binary tree, return the sum of every tree node's tilt.
The tilt of a node is the absolute difference between the sum of all the left subtree node's values and all of the right subtree node's values. If a node does not exist, then the sum will be zero.
Example 1:
Input: root = [1,2,3]
Output: 1
Explanation:
Tilt of node 1: |2 − 3| = 1.
Tilt of node 2: |0 − 0| = 0.
Tilt of node 3: |0 − 0| = 0.
The sum of every node's tilt is 1.
Example 2:
Input: root = [4,2,9,3,5,null,7]
Output: 15
Explanation:
Tilt of node 4: |11 − 13| = 2.
Tilt of node 9: |0 − 7| = 7.
Tilt of node 5: |3 − 0| = 3.
Tilt of node 7: |0 − 0| = 0.
Tilt of node 2: |3 − 0| = 3.
Tilt of node 3: |0 − 0| = 0.
The sum of every node's tilt is 2 + 7 + 3 + 0 + 3 + 0 = 15.
Constraints:
- The number of nodes in the tree is in the range
[1, 10⁴].0 <= Node.val <= 200
Code and Explanation
- Postorder DFS computes each subtree's sum bottom-up.
- At each node, add
|left_sum − right_sum|to the global tilt. - Return
node.val + left_sum + right_sumto the parent.
Time: O(n) | Space: O(h)
- Explicit postorder stack with a visited flag tracks processing order.
- Store subtree sums in a hash map; accumulate tilt when a node is finalized.
- Same logic as recursion without call-stack depth concerns.
Time: O(n) | Space: O(n)
Problem 3: Diameter of Binary Tree (Leetcode:543)#
Problem Statement
Given the root of a binary tree, return the length of the diameter of the tree.
The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.
The length of a path between two nodes is represented by the number of edges between them.
Example 1:
Input: root = [1,2,3,4,5]
Output: 3
Explanation: 3 is the length of the path [4,2,1,3] or [5,2,1,3].
Example 2:
Input: root = [1,2]
Output: 1
Constraints:
- The number of nodes in the tree is in the range
[1, 10⁴].-100 <= Node.val <= 100
Code and Explanation
- Diameter at a node = longest path through it =
left_height + right_height. - Postorder height DFS updates global max while returning subtree height.
- Count edges, not nodes — heights exclude the current node.
Time: O(n) | Space: O(h)
- Simulate postorder to compute heights bottom-up without recursion.
- Update diameter whenever a node's left and right heights are known.
- Useful when recursion depth is a concern on very tall trees.
Time: O(n) | Space: O(n)
Problem 4: Merge Two Binary Trees (Leetcode:617)#
Problem Statement
You are given two binary trees root1 and root2.
Imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge the two trees into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the non-null node will be used as the node of the new tree.
Return the merged tree.
Example 1:
Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
Output: [3,4,5,5,4,null,7]
Example 2:
Input: root1 = [1], root2 = [1,2]
Output: [2,2]
Constraints:
- The number of nodes in both trees is in the range
[0, 2000].-10⁴ <= Node.val <= 10⁴
Code and Explanation
- If one tree is empty, return the other as the merged subtree.
- Sum values at overlapping nodes and recurse on both children.
- Reuse
root1in place to avoid extra node allocation.
Time: O(min(m, n)) | Space: O(h)
- Stack pairs of corresponding nodes from both trees.
- Sum values; push both children when both exist, otherwise attach the non-null child.
- Same merge logic as recursion in iterative form.
Time: O(min(m, n)) | Space: O(h)
Problem 5: Minimum Depth of Binary Tree (Leetcode:111)#
Problem Statement
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: 2
Example 2:
Input: root = [2,null,3,null,4,null,5,null,6]
Output: 5
Constraints:
- The number of nodes in the tree is in the range
[0, 10⁵].-1000 <= Node.val <= 1000
Code and Explanation
- Minimum depth = shortest root-to-leaf path (must reach a leaf).
- If one child is missing, follow the non-null side — a single-child node is not a leaf.
- Both children present:
1 + min(left, right).
Time: O(n) | Space: O(h)
- BFS finds the shallowest node first — ideal for minimum depth.
- Return immediately when a leaf (no children) is dequeued.
- Avoids traversing deeper levels once the first leaf is found.
Time: O(n) | Space: O(w)
Problem 6: Balanced Binary Tree (Leetcode:110)#
Problem Statement
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the depth of the two subtrees of every node never differ by more than one.
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: true
Example 2:
Input: root = [1,2,2,3,3,null,null,4,4]
Output: false
Explanation: The left subtree of node 1 has a depth of 3, while the right subtree has a depth of 1.
Example 3:
Input: root = []
Output: true
Constraints:
- The number of nodes in the tree is in the range
[0, 5000].-10⁴ <= Node.val <= 10⁴
Code and Explanation
- Balanced iff every node's subtrees differ in height by at most 1.
- Return −1 as a sentinel when imbalance is detected; propagate up immediately.
- Single DFS pass computes height and checks balance together — O(n), not O(n²).
Time: O(n) | Space: O(h)
- Postorder iteration computes subtree heights bottom-up.
- Check balance at each node when both child heights are known.
- Return
Falseimmediately on the first imbalance.
Time: O(n) | Space: O(n)
Problem 7: Maximum Depth of Binary Tree (Leetcode:104)#
Problem Statement
Given the root of a binary tree, return its maximum depth.
A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: 3
Example 2:
Input: root = [1,null,2]
Output: 2
Constraints:
- The number of nodes in the tree is in the range
[0, 10⁴].-100 <= Node.val <= 100
Code and Explanation
- Depth of a node = 1 + max depth of its subtrees.
- Base case: empty tree has depth 0.
- Classic divide-and-conquer on left and right children.
Time: O(n) | Space: O(h)
- BFS processes one level per outer loop iteration.
- Increment depth after draining the current level's queue snapshot.
- Count levels rather than recursing — natural for level-wise thinking.
Time: O(n) | Space: O(w)
Problem 8: Same Tree (Leetcode:100)#
Problem Statement
Given the roots of two binary trees p and q, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.
Example 1:
Input: p = [1,2,3], q = [1,2,3]
Output: true
Example 2:
Input: p = [1,2], q = [1,null,2]
Output: false
Example 3:
Input: p = [1,2,1], q = [1,1,2]
Output: false
Constraints:
- The number of nodes in both trees is in the range
[0, 100].-10⁴ <= Node.val <= 10⁴
Code and Explanation
- Both null → trees match at this branch.
- One null or different values → not the same tree.
- Recurse on both left and right pairs.
Time: O(n) | Space: O(h)
- BFS queue holds pairs of nodes to compare simultaneously.
- Mismatch on structure or value → return
Falseimmediately. - Enqueue both child pairs for continued comparison.
Time: O(n) | Space: O(w)
Problem 9: Symmetric Tree (Leetcode:101)#
Problem Statement
Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).
Example 1:
Input: root = [1,2,2,3,4,4,3]
Output: true
Example 2:
Input: root = [1,2,2,null,3,null,3]
Output: false
Constraints:
- The number of nodes in the tree is in the range
[1, 1000].-100 <= Node.val <= 100
Code and Explanation
- Mirror check: compare
left.leftwithright.rightandleft.rightwithright.left. - Both subtrees must be mirrors at every level.
- Empty tree is symmetric by definition.
Time: O(n) | Space: O(h)
- Queue pairs of mirror-position nodes from left and right subtrees.
- Enqueue outer pair
(left.left, right.right)and inner pair(left.right, right.left). - Same mirror logic as recursion without call-stack depth.
Time: O(n) | Space: O(w)
Binary Search Trees#
Problem 1: Search in a Binary Search Tree (Leetcode:700)#
Problem Statement
You are given the root of a binary search tree (BST) and an integer val.
Find the node in the BST that the node's value equals val and return the subtree rooted with that node. If such a node does not exist, return null.
Example 1:
Input: root = [4,2,7,1,3], val = 2
Output: [2,1,3]
Explanation: Subtree rooted at node with value 2.
Example 2:
Input: root = [4,2,7,1,3], val = 5
Output: []
Constraints:
- The number of nodes in the tree is in the range
[1, 5000].1 <= Node.val <= 10⁷rootis a valid binary search tree.1 <= val <= 10⁷
Code and Explanation
- BST property: All values in the left subtree are smaller; all in the right are larger.
- Base case: Return the node when found, or
Nonewhen the subtree is empty. - Recurse left if
valis smaller, otherwise right.
Time: O(h) | Space: O(h)
- Walk from root following the BST ordering rule at each step.
- Stop when the target is found or the current pointer becomes
None. - No recursion — constant auxiliary space aside from the pointer.
Time: O(h) | Space: O(1)
Problem 2: Two Sum IV - Input is a BST (Leetcode:653)#
Problem Statement
Given the root of a binary search tree and an integer k, return true if there exist two elements in the BST such that their sum is equal to k. Otherwise, return false.
Example 1:
Input: root = [5,3,6,2,4,null,7], k = 9
Output: true
Example 2:
Input: root = [5,3,6,2,4,null,7], k = 28
Output: false
Constraints:
- The number of nodes in the tree is in the range
[1, 10⁴].-10⁴ <= Node.val <= 10⁴rootis a valid binary search tree.-10⁵ <= k <= 10⁵
Code and Explanation
- DFS the tree and store every visited value in a hash set.
- Before inserting, check whether
k - node.valwas seen already. - Short-circuit on the first matching pair.
Time: O(n) | Space: O(n)
- Inorder traversal of a BST yields a sorted array.
- Run the classic two-pointer scan on that sorted list.
- Uses BST ordering explicitly instead of a hash set.
Time: O(n) | Space: O(n)
Problem 3: Minimum Absolute Difference in BST (Leetcode:530)#
Problem Statement
Given the root of a Binary Search Tree (BST), return the minimum absolute difference between the values of any two different nodes in the tree.
Example 1:
Input: root = [4,2,6,1,3]
Output: 1
Example 2:
Input: root = [1,0,48,null,null,12,49]
Output: 1
Constraints:
- The number of nodes in the tree is in the range
[2, 10⁴].0 <= Node.val <= 10⁵
Code and Explanation
- Inorder visits nodes in sorted order in a BST.
- Track the previous value and update the minimum adjacent gap.
- The answer is the smallest difference between consecutive inorder values.
Time: O(n) | Space: O(h)
- Simulate recursive inorder with an explicit stack.
- Each time a node is popped, compare it with the previous visited value.
- Same logic as the recursive version without call-stack overhead.
Time: O(n) | Space: O(h)
Problem 4: Range Sum of BST (Leetcode:938)#
Problem Statement
Given the root of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high].
Example 1:
Input: root = [10,5,15,3,7,null,18], low = 7, high = 15
Output: 32
Explanation: Nodes 7, 10, and 15 are in the range [7, 15]. 7 + 10 + 15 = 32.
Example 2:
Input: root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10
Output: 23
Explanation: Nodes 6, 7, and 10 are in the range [6, 10]. 6 + 7 + 10 = 23.
Constraints:
- The number of nodes in the tree is in the range
[1, 2 × 10⁴].1 <= Node.val <= 10⁵1 <= low <= high <= 10⁵- All
Node.valare unique.
Code and Explanation
- Prune branches that cannot contain values in
[low, high]. - If the current value is inside the range, include it and search both subtrees.
- BST ordering avoids visiting entire subtrees that are out of range.
Time: O(n) | Space: O(h)
- Explicit stack replaces recursion while keeping the same pruning rules.
- Only nodes inside the range contribute to the running sum.
- Skipped subtrees are never pushed onto the stack.
Time: O(n) | Space: O(h)
Problem 5: Delete Node in a BST (Leetcode:450)#
Problem Statement
Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.
Basically, the value that was in the node key before deletion should take on the value of its in-order predecessor or successor. Then, the node with key should be deleted.
Example 1:
Input: root = [5,3,6,2,4,null,7], key = 3
Output: [5,4,6,2,null,null,7]
Explanation: Given key to delete is 3. So we find the node with value 3 and delete it. One valid answer is [5,4,6,2,null,null,7], shown in the above BST. Please notice that another valid answer is [5,2,6,null,4,null,7] and it's also accepted.
Example 2:
Input: root = [5,3,6,2,4,null,7], key = 0
Output: [5,3,6,2,4,null,7]
Explanation: The tree does not contain a node with value 0.
Example 3:
Input: root = [5,3,6,2,4,null,7], key = 7
Output: [5,3,6,2,4]
Constraints:
- The number of nodes in the tree is in the range
[0, 10⁴].-10⁵ <= Node.val <= 10⁵- Each node has a unique value.
rootis a valid binary search tree.-10⁵ <= key <= 10⁵
Code and Explanation
- Search for the target using BST ordering.
- 0/1 child: splice the node out by returning its non-null child.
- Two children: copy the inorder successor value, then delete that successor from the right subtree.
Time: O(h) | Space: O(h)
- Dummy node simplifies deleting the root.
- Walk down with a parent pointer until the target is found.
- Apply the same three deletion cases without recursion.
Time: O(h) | Space: O(1)
Problem 6: Trim a Binary Search Tree (Leetcode:669)#
Problem Statement
Given the root of a binary search tree and the lowest and highest boundaries as low and high, trim the tree so that all its elements lies in [low, high]. Trimming the tree should not change the relative structure of the elements that will remain (i.e., any node's descendant should remain a descendant).
Return the new root of the trimmed binary search tree.
Example 1:
Input: root = [1,0,2], low = 1, high = 2
Output: [1,null,2]
Example 2:
Input: root = [3,0,4,null,2,null,null,1], low = 1, high = 3
Output: [3,2,null,1]
Constraints:
- The number of nodes in the tree is in the range
[1, 10⁴].0 <= Node.val <= 10⁴- The value of each node in the tree is unique.
0 <= low <= high <= 10⁴rootis a valid binary search tree.
Code and Explanation
- If the current value is below
low, the whole left side is invalid — recurse right. - If above
high, recurse left instead. - Otherwise trim both subtrees and keep the current node.
Time: O(n) | Space: O(h)
- Collect in-range values via inorder traversal.
- Rebuild a balanced BST from the filtered sorted array.
- Different trade-off: extra space, but produces a height-balanced result.
Time: O(n) | Space: O(n)
Problem 7: Insert into a Binary Search Tree (Leetcode:701)#
Problem Statement
You are given the root node of a binary search tree (BST) and a val to insert into the tree. Return the root node of the BST after the insertion. It is guaranteed that the new value does not exist in the original BST.
Notice that there may exist multiple valid ways for the insertion, as long as the tree remains a BST after insertion. You can return any of them.
Example 1:
Input: root = [4,2,7,1,3], val = 5
Output: [4,2,7,1,3,5,null,null,null,null,null,null,null]
Explanation: Another accepted tree is shown below.
Example 2:
Input: root = [40,20,60,10,30,50,70], val = 25
Output: [40,20,60,10,30,50,70,null,null,25]
Example 3:
Input: root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
Output: [4,2,7,1,3,5]
Constraints:
- The number of nodes in the tree will be in the range
[0, 10⁴].-10⁸ <= Node.val <= 10⁸- All the values
Node.valare unique.-10⁸ <= val <= 10⁸- It's guaranteed that
valdoes not exist in the original BST.
Code and Explanation
- Empty spot: create a new leaf when
rootisNone. - Go left if
valis smaller, otherwise go right. - Return the unchanged subtree root after linking the new node.
Time: O(h) | Space: O(h)
- Walk down until the correct empty child slot is found.
- Attach the new node directly without recursive calls.
- Original root reference is preserved and returned.
Time: O(h) | Space: O(1)
Problem 8: Kth Smallest Element in a BST (Leetcode:230)#
Problem Statement
Given the root of a binary search tree, and an integer k, return the kth smallest value (1-indexed) of all the values of the nodes in the tree.
Example 1:
Input: root = [3,1,4,null,2], k = 1
Output: 1
Example 2:
Input: root = [5,3,6,2,4,null,null,1], k = 3
Output: 3
Constraints:
- The number of nodes in the tree is
n.1 <= k <= n <= 10⁴0 <= Node.val <= 10⁴
Follow up: If the BST is modified often (i.e., we can do insert and delete operations) and you need to find the kth smallest frequently, how would you optimize?
Code and Explanation
- Inorder traversal visits BST nodes from smallest to largest.
- Decrement
keach time a node is visited. - Stop early once the k-th smallest value is recorded.
Time: O(h + k) | Space: O(h)
- Standard iterative inorder using a stack.
- Count nodes as they are popped in sorted order.
- Return immediately when the count reaches
k.
Time: O(h + k) | Space: O(h)
Problem 9: All Elements in Two Binary Search Trees (Leetcode:1305)#
Problem Statement
Given two binary search trees root1 and root2, return a list containing all the integers from both trees sorted in ascending order.
Example 1:
Input: root1 = [2,1,4], root2 = [1,0,3]
Output: [0,1,1,2,3,4]
Example 2:
Input: root1 = [1,null,8], root2 = [8,1]
Output: [1,1,8,8]
Constraints:
- The number of nodes in each tree is in the range
[0, 5000].-10⁵ <= Node.val <= 10⁵
Code and Explanation
- Flatten both BSTs to sorted arrays via inorder traversal.
- Merge the two sorted arrays with a two-pointer scan.
- Simple and easy to reason about.
Time: O(m + n) | Space: O(m + n)
- Each stack simulates inorder traversal lazily for one tree.
- Compare stack tops and advance the smaller side — like merging linked lists.
- Avoids storing full inorder arrays upfront.
Time: O(m + n) | Space: O(h1 + h2)
Problem 10: Binary Search Tree Iterator (Leetcode:173)#
Problem Statement
Implement the BSTIterator class that represents an iterator over the in-order traversal of a binary search tree (BST):
BSTIterator(TreeNode root)Initializes an object of theBSTIteratorclass. Therootof the BST is given as part of the constructor. The pointer should be initialized to a non-existent number smaller than any element in the BST.boolean hasNext()Returnstrueif there exists a number in the traversal to the right of the pointer, otherwise returnsfalse.int next()Moves the pointer to the right, then returns the number at the pointer.
Notice that by initializing the pointer to a non-existent number, the first call to next() will return the smallest element in the BST.
You may assume that next() calls will always be valid. That is, there will be at least a next number in the in-order traversal when next() is called.
Example 1:
Input:
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
Output:[null, 3, 7, true, 9, true, 13, true, 15, true, 20, false]
Explanation:
Constraints:
- The number of nodes in the tree is in the range
[1, 10⁵].0 <= Node.val <= 10⁶- At most
10⁵calls will be made tohasNext, andnext.
Code and Explanation
- Precompute the full inorder list during construction.
next()andhasNext()become array index operations.- Fast per-call cost, but O(n) upfront space.
Time: O(n) init, O(1) per call | Space: O(n)
- Only materialize the next value when
next()is called. - Stack always holds the path to the next smallest unvisited node.
- Better space for sparse
next()calls on large trees.
Time: O(1) amortized per call | Space: O(h)
Problem 11: Binary Search Tree to Greater Sum Tree (Leetcode:1038)#
Problem Statement
Given the root of a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus the sum of all keys greater than the original key in BST.
As a reminder, a binary search tree maintains the following property for every node:
Node.left.val < Node.val < Node.right.val
Return the root of the Greater Tree.
Example 1:
Input: root = [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
Output: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
Example 2:
Input: root = [0,null,1]
Output: [1,null,1]
Constraints:
- The number of nodes in the tree is in the range
[1, 100].0 <= Node.val <= 100- All the values in the tree are unique.
Note: This question is the same as 538: https://leetcode.com/problems/convert-bst-to-greater-tree/
Code and Explanation
- Reverse inorder visits nodes from largest to smallest.
- Maintain a running sum of all nodes already visited.
- Overwrite each node with that cumulative sum.
Time: O(n) | Space: O(h)
- Push right spine first, then pop and update — reverse inorder with a stack.
- Same running-sum logic as the recursive version.
- Avoids recursion depth on skewed trees.
Time: O(n) | Space: O(h)
Problem 12: Maximum Sum BST in Binary Tree (Leetcode:1373)#
Problem Statement
Given a root of a binary tree, return the maximum sum of all keys in any BST that is also a subtree in the given binary tree.
Example 1:
Input: root = [1,4,3,4,null,5,5]
Output: 20
Explanation: Maximum sum in a valid BST is obtained in the subtree rooted at node 3 with keys 3, 4, and 5.
Example 2:
Input: root = [4,3,null,1,2]
Output: 2
Explanation: Maximum sum in a valid BST is obtained in the subtree rooted at node 1 with keys 1 and 2.
Example 3:
Input: root = [-4,-2,-5,-1,-3,null,2]
Output: 6
Explanation: Maximum sum in a valid BST is obtained in the subtree rooted at node 2 with key 2.
Constraints:
- The number of nodes in the tree is in the range
[1, 4 × 10⁴].-4 × 10⁴ <= Node.val <= 4 × 10⁴
Code and Explanation
- Postorder DFS returns whether a subtree is a valid BST plus its min, max, and sum.
- If both children are valid BSTs and bounds match, the current subtree is a BST too.
- Track the maximum BST sum seen globally.
Time: O(n) | Space: O(h)
- Try every node as the root of a candidate BST subtree.
- Validate BST property with min/max bounds and compute subtree sum.
- Correct but revisits nodes repeatedly — useful contrast to the linear approach.
Time: O(n²) worst case | Space: O(h)
Path#
Problem 1: Binary Tree Paths (Leetcode:257)#
Problem Statement
Given the root of a binary tree, return all root-to-leaf paths in any order**.
A leaf is a node with no children.
Example 1:
Input: root = [1,2,3,null,5]
Output: ["1->2->5","1->3"]
Example 2:
Input: root = [1]
Output: ["1"]
Constraints:
- The number of nodes in the tree is in the range
[1, 100].-100 <= Node.val <= 100
Code and Explanation
- Build the path string as DFS descends from root to leaf.
- At a leaf, append the complete
"a->b->c"string to the answer. - Backtracking is implicit via passing updated path strings.
Time: O(n) | Space: O(h)
- Stack stores
(node, path_so_far)pairs. - Push children with extended path strings before popping the next state.
- Same output as recursive DFS without recursion.
Time: O(n) | Space: O(h)
Problem 2: Path Sum (Leetcode:112)#
Problem Statement
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.
Example 1:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
Output: true
Explanation:
The root-to-leaf path with the target sum is shown.
Example 2:
Input: root = [1,2,3], targetSum = 5
Output: false
Explanation:
There are two root-to-leaf paths in the tree:
(1 --> 2): The sum is 3.
(1 --> 3): The sum is 4.
There is no root-to-leaf path with sum = 5.
Example 3:
Input: root = [], targetSum = 0
Output: false
Explanation:
Since the tree is empty, there are no root-to-leaf paths.
Constraints:
- The number of nodes in the tree is in the range
[0, 5000].-1000 <= Node.val <= 1000-1000 <= targetSum <= 1000
Code and Explanation
- Subtract the current value from the remaining target as you descend.
- At a leaf, check whether the remaining sum equals zero.
- Return true if either subtree yields a valid root-to-leaf path.
Time: O(n) | Space: O(h)
- Stack entries track remaining sum needed from the current node to a leaf.
- Early return when a leaf satisfies
remaining == 0. - Equivalent logic to the recursive version.
Time: O(n) | Space: O(h)
Problem 3: Path Sum II (Leetcode:113)#
Problem Statement
Given the root of a binary tree and an integer targetSum, return all root-to-leaf paths where the sum of the node values in the path equals targetSum. Each path should be returned as a list of the node values, not node references.
A root-to-leaf path is a path starting from the root and ending at any leaf node. A leaf is a node with no children.
Example 1:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: [[5,4,11,2],[5,8,4,5]]
Explanation:
There are two paths whose sum equals targetSum:
5 + 4 + 11 + 2 = 22
5 + 8 + 4 + 5 = 22
Example 2:
Input: root = [1,2,3], targetSum = 5
Output: []
Example 3:
Input: root = [1,2], targetSum = 0
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 5000].-1000 <= Node.val <= 1000-1000 <= targetSum <= 1000
Code and Explanation
- Track the current path in a list while DFS walks the tree.
- At a leaf where the remaining sum equals the leaf value, copy the path into the answer.
- Backtrack with
path.pop()after exploring each branch.
Time: O(n) | Space: O(h)
- Each stack frame stores the node, remaining sum, and path list so far.
- Valid leaf paths are collected when
remaining == 0. - Child paths are built by copying and extending the parent path.
Time: O(n) | Space: O(h)
Problem 4: Sum Root to Leaf Numbers (Leetcode:129)#
Problem Statement
You are given the root of a binary tree containing digits from 0 to 9 only.
Each root-to-leaf path in the tree represents a number.
Return the total sum of all root-to-leaf numbers. Test cases are generated so that the answer will fit in a 32-bit integer.
A leaf node is a node with no children.
Example 1:
Input: root = [1,2,3]
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.
Example 2:
Input: root = [4,9,0,5,1]
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.
Constraints:
- The number of nodes in the tree is in the range
[1, 1000].0 <= Node.val <= 9- The depth of the tree will not exceed
10.
Code and Explanation
- Build the number top-down by shifting left (
* 10) and adding the digit. - At a leaf, return the completed number.
- Sum the leaf numbers from all root-to-leaf paths.
Time: O(n) | Space: O(h)
- BFS queue stores
(node, number_so_far)pairs. - Extend the running number when enqueueing children.
- Add to
totalwhenever a leaf is dequeued.
Time: O(n) | Space: O(w)
Problem 5: Binary Tree Maximum Path Sum (Leetcode:124)#
Problem Statement
A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root.
The path sum of a path is the sum of the node's values in the path.
Given the root of a binary tree, return the maximum path sum of any non-empty path.
Example 1:
Input: root = [1,2,3]
Output: 6
Explanation:
The optimal path is 2 -> 1 -> 3 with a path sum of 2 + 1 + 3 = 6.
Example 2:
Input: root = [-10,9,20,null,null,15,7]
Output: 42
Explanation:
The optimal path is 15 -> 20 -> 7 with a path sum of 15 + 20 + 7 = 42.
Constraints:
- The number of nodes in the tree is in the range
[1, 3 * 104].-1000 <= Node.val <= 1000
Code and Explanation
gain(node)returns the best downward path sum starting atnode(one branch only).- Ignore negative contributions by clamping child gains to zero.
- A path through
nodecan use left + node + right; update the global maximum.
Time: O(n) | Space: O(h)
- Build a postorder list iteratively with a visited set.
- Process nodes bottom-up, storing each node's best downward gain in a map.
- Same recurrence as recursion, but without the call stack.
Time: O(n) | Space: O(n)
Problem 6: Path Sum III (Leetcode:437)#
Problem Statement
Given the root of a binary tree and an integer targetSum, return the number of paths where the sum of the values along the path equals targetSum.
The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes).
Example 1:
Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation:
The paths that sum to 8 are shown.
Example 2:
Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: 3
Constraints:
- The number of nodes in the tree is in the range
[0, 1000].-109 9-1000 <= targetSum <= 1000
Code and Explanation
- Prefix sums along the current root-to-node path are stored in a hash map.
- If
curr - targetSumexists, a valid downward path ending here was found. - Backtrack prefix counts when returning from a subtree.
Time: O(n) | Space: O(h)
- For each node, count paths that start there and sum to
targetSum. - Recurse into both children to cover all possible start points.
- Simple but revisits paths — O(n²) worst case on skewed trees.
Time: O(n²) worst case | Space: O(h)
Problem 7: Pseudo-Palindromic Paths in a Binary Tree (Leetcode:1457)#
Problem Statement
Given a binary tree where node values are digits from 1 to 9. A path in the binary tree is said to be pseudo-palindromic if at least one permutation of the node values in the path is a palindrome.
Return the number of pseudo-palindromic paths going from the root node to leaf nodes.
Example 1:
Input: root = [2,3,1,3,1,null,1]
Output: 2
Explanation:
The figure above represents the given binary tree. There are three paths going from the root node to leaf nodes: the red path [2,3,3], the green path [2,1,1], and the path [2,3,1]. Among these paths only red path and green path are pseudo-palindromic paths since the red path [2,3,3] can be rearranged in [3,2,3] (palindrome) and the green path [2,1,1] can be rearranged in [1,2,1] (palindrome).
Example 2:
Input: root = [2,1,1,1,3,null,null,null,null,null,1]
Output: 1
Explanation:
The figure above represents the given binary tree. There are three paths going from the root node to leaf nodes: the green path [2,1,1], the path [2,1,3,1], and the path [2,1]. Among these paths only the green path is pseudo-palindromic since [2,1,1] can be rearranged in [1,2,1] (palindrome).
Example 3:
Input: root = [9]
Output: 1
Constraints:
- The number of nodes in the tree is in the range
[1, 105].1 <= Node.val <= 9
Code and Explanation
- Toggle a bit for each digit (1–9) as the path descends.
- A path can form a palindrome when at most one digit has odd frequency.
- That means the bitmask is 0 or a single power of two.
Time: O(n) | Space: O(h)
- Track digit counts in a length-10 array (values are 1–9).
- At each leaf, count how many digits appear an odd number of times.
- Valid when at most one odd count — explicit version of the bitmask check.
Time: O(n) | Space: O(h)
construct a binary tree/BST#
Problem 1: Construct Binary Tree from Preorder and Inorder Traversal (Leetcode:105)#
Problem Statement
Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and inorder is the inorder traversal of the same tree, construct and return the binary tree.
Example 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
Example 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
Constraints:
1 <= preorder.length <= 3000inorder.length == preorder.length-3000 <= preorder[i], inorder[i] <= 3000preorderandinorderconsist of unique values.- Each value of
inorderalso appears inpreorder.preorderis guaranteed to be the preorder traversal of the tree.inorderis guaranteed to be the inorder traversal of the tree.
Code and Explanation
- Preorder gives the root; inorder locates the split between left and right subtrees.
- Hash map finds the root index in inorder in O(1).
- Recurse on
[left, mid-1]and[mid+1, right].
Time: O(n) | Space: O(n)
- Stack tracks the path of nodes whose right child is not yet assigned.
- If the next preorder value belongs left of the stack top in inorder, attach as left child.
- Otherwise pop until the correct parent is found, then attach as right child.
Time: O(n) | Space: O(h)
Problem 2: Construct Binary Tree from Inorder and Postorder Traversal (Leetcode:106)#
Problem Statement
Given two integer arrays inorder and postorder where inorder is the inorder traversal of a binary tree and postorder is the postorder traversal of the same tree, construct and return the binary tree.
Example 1:
Input: inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
Output: [3,9,20,null,null,15,7]
Example 2:
Input: inorder = [-1], postorder = [-1]
Output: [-1]
Constraints:
1 <= inorder.length <= 3000postorder.length == inorder.length-3000 <= inorder[i], postorder[i] <= 3000inorderandpostorderconsist of unique values.- Each value of
postorderalso appears ininorder.inorderis guaranteed to be the inorder traversal of the tree.postorderis guaranteed to be the postorder traversal of the tree.
Code and Explanation
- Postorder's last element is always the subtree root.
- Find that root in inorder to split left/right ranges.
- Build right subtree first because postorder is consumed from the end.
Time: O(n) | Space: O(n)
- Process postorder from right to left, mirroring the recursive pointer walk.
- Stack holds nodes awaiting a left or right assignment.
- Compare against inorder from the end to decide attachment side.
Time: O(n) | Space: O(h)
Problem 3: Construct Binary Tree from Preorder and Postorder Traversal (Leetcode:889)#
Problem Statement
Given two integer arrays, preorder and postorder where preorder is the preorder traversal of a binary tree of distinct values and postorder is the postorder traversal of the same tree, reconstruct and return the binary tree.
If there exist multiple answers, you can return any of them.
Example 1:
Input: preorder = [1,2,4,5,3,6,7], postorder = [4,5,2,6,7,3,1]
Output: [1,2,3,4,5,6,7]
Example 2:
Input: preorder = [1], postorder = [1]
Output: [1]
Constraints:
1 <= preorder.length <= 301 <= preorder[i] <= preorder.length- All the values of
preorderare unique.postorder.length == preorder.length1 <= postorder[i] <= postorder.length- All the values of
postorderare unique.- It is guaranteed that
preorderandpostorderare the preorder traversal and postorder traversal of the same binary tree.
Code and Explanation
- First preorder value is the root; second preorder value starts the left subtree.
- Find that left-root value in postorder — everything before its last occurrence is the left subtree.
- Recurse on the left and right slices.
Time: O(n²) worst case | Space: O(n)
- Index map avoids repeated
post.index()scans. - Left subtree size is derived from where the left child appears in postorder.
- Same split logic as Approach 1, but O(n) total with pointer-based slicing.
Time: O(n) | Space: O(n)
Problem 4: Convert Sorted Array to Binary Search Tree (Leetcode:108)#
Problem Statement
Given an integer array nums where the elements are sorted in ascending order, convert it to a height-balanced binary search tree.
Example 1:
Input: nums = [-10,-3,0,5,9]
Output: [0,-3,9,-10,null,5]
Explanation:
[0,-10,5,null,-3,null,9] is also accepted:
![]()
Example 2:
Input: nums = [1,3]
Output: [3,1]
Explanation:
[1,null,3] and [3,1] are both height-balanced BSTs.
Constraints:
1 4-104 4numsis sorted in a strictly increasing order.
Code and Explanation
- Pick the middle element as the root to keep the tree balanced.
- Recursively build left half and right half of the array.
- Result is a height-balanced BST.
Time: O(n) | Space: O(log n)
- Insert each value using standard BST insertion.
- Sorted input produces a skewed tree, not a balanced one.
- Useful contrast: simpler code, but O(n log n) time and O(n) height worst case.
Time: O(n log n) | Space: O(n) worst case
Problem 5: Construct Binary Search Tree from Preorder Traversal (Leetcode:1008)#
Problem Statement
Given an array of integers preorder, which represents the preorder traversal of a BST (i.e., binary search tree), construct the tree and return its root.
It is guaranteed that there is always possible to find a binary search tree with the given requirements for the given test cases.
A binary search tree is a binary tree where for every node, any descendant of Node.left has a value strictly less than Node.val, and any descendant of Node.right has a value strictly greater than Node.val.
A preorder traversal of a binary tree displays the value of the node first, then traverses Node.left, then traverses Node.right.
Example 1:
Input: preorder = [8,5,1,7,10,12]
Output: [8,5,10,1,7,null,12]
Example 2:
Input: preorder = [1,3]
Output: [1,null,3]
Constraints:
1 <= preorder.length <= 1001 <= preorder[i] <= 1000- All the values of
preorderare unique.
Code and Explanation
- Preorder for a BST visits parent before children; each node has an upper bound from its ancestors.
- Build the left child first (values must be
< current), then the right child (values< bound). - A single index walks the preorder array once.
Time: O(n) | Space: O(h)
- Stack tracks ancestors whose right child may still be extended.
- If the new value is smaller than the top, it belongs in the left subtree.
- Otherwise pop until finding the correct parent, then attach as right child.
Time: O(n) | Space: O(h)
View Problem#
Problem 1: Binary Tree Right Side View (Leetcode:199)#
Problem Statement
Given the root of a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.
Example 1:
Example 2:
Example 3:
Example 4:
Constraints:
- The number of nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
Code and Explanation
- BFS visits the tree level by level.
- The last node processed at each level is the rightmost visible node.
- Append its value before moving to the next level.
Time: O(n) | Space: O(w)
- Visit right subtree before left so the first node at each depth is rightmost.
- When
depth == len(result), this depth has not been recorded yet — append the value. - Same output as BFS with a depth-first traversal.
Time: O(n) | Space: O(h)
Lowest Common Ancestor#
Problem 1: Lowest Common Ancestor of a Binary Tree (Leetcode:236)#
Problem Statement
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation:
The LCA of nodes 5 and 1 is 3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation:
The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Example 3:
Input: root = [1,2], p = 1, q = 2
Output: 1
Constraints:
- The number of nodes in the tree is in the range
[2, 105].-109 9- All
Node.valare unique.p != qpandqwill exist in the tree.
Code and Explanation
- Postorder search: recurse left and right; if both return non-null, current node is the LCA.
- If only one side finds a target (or an ancestor of a target), bubble that result up.
- Base case:
None, or hittingp/qdirectly.
Time: O(n) | Space: O(h)
- Build a parent map via iterative DFS until both
pandqare discovered. - Walk
pup to root, storing every ancestor in a set. - Walk
qupward until hitting a shared ancestor — that node is the LCA.
Time: O(n) | Space: O(n)
Problem 2: Lowest Common Ancestor of a Binary Search Tree (Leetcode:235)#
Problem Statement
Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Example 1:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation:
The LCA of nodes 2 and 8 is 6.
Example 2:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation:
The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
Example 3:
Input: root = [2,1], p = 2, q = 1
Output: 2
Constraints:
- The number of nodes in the tree is in the range
[2, 105].-109 9- All
Node.valare unique.p != qpandqwill exist in the BST.
Code and Explanation
- BST ordering: if both targets are smaller, LCA lies in the left subtree; if both larger, go right.
- Otherwise the current node sits between them (or equals one) — it is the LCA.
- No full-tree search needed.
Time: O(h) | Space: O(1)
- Same BST split logic as the iterative version.
- Recurse into the subtree that contains both nodes.
- Return the node where paths diverge.
Time: O(h) | Space: O(h)
Problem 3: Lowest Common Ancestor of Deepest Leaves (Leetcode:1123)#
Problem Statement
Given the root of a binary tree, return the lowest common ancestor of its deepest leaves.
Recall that:
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4]
Output: [2,7,4]
Explanation:
We return the node with value 2, colored in yellow in the diagram.
The nodes coloured in blue are the deepest leaf-nodes of the tree.
Note that nodes 6, 0, and 8 are also leaf nodes, but the depth of them is 2, but the depth of nodes 7 and 4 is 3.
Example 2:
Input: root = [1]
Output: [1]
Explanation:
The root is the deepest node in the tree, and it's the lca of itself.
Example 3:
Input: root = [0,1,3,null,2]
Output: [2]
Explanation:
The deepest leaf node in the tree is 2, the lca of one node is itself.
Constraints:
- The number of nodes in the tree will be in the range
[1, 1000].0 <= Node.val <= 1000- The values of the nodes in the tree are unique.
Code and Explanation
- Return
(depth, lca_candidate)from each subtree. - If left and right depths differ, propagate the deeper side's LCA upward.
- If equal, current node is the LCA of all deepest leaves below it.
Time: O(n) | Space: O(h)
- BFS finds all deepest leaves and records their depth.
- Build a parent map, then pairwise LCA-merge the deepest nodes.
- Correct but heavier than the single-pass postorder approach.
Time: O(n) | Space: O(n)
Validate Trees#
Problem 1: Validate Binary Tree Nodes (Leetcode:1361)#
Problem Statement
You have n binary tree nodes numbered from 0 to n - 1 where node i has two children leftChild[i] and rightChild[i], return true if and only if all the given nodes form exactly one valid binary tree.
If node i has no left child then leftChild[i] will equal -1, similarly for the right child.
Note that the nodes have no values and that we only use the node numbers in this problem.
Example 1:
Input: n = 4, leftChild = [1,-1,3,-1], rightChild = [2,-1,-1,-1]
Output: true
Example 2:
Input: n = 4, leftChild = [1,-1,3,-1], rightChild = [2,3,-1,-1]
Output: false
Example 3:
Input: n = 2, leftChild = [1,0], rightChild = [-1,-1]
Output: false
Constraints:
n == leftChild.length == rightChild.length1 4-1 <= leftChild[i], rightChild[i] <= n - 1
Code and Explanation
- A valid binary tree has exactly one root (parent count 0) and every other node has exactly one parent.
- Reject immediately if any node has more than one parent.
- DFS from the root must visit all n nodes — catches disconnected components and cycles.
Time: O(n) | Space: O(n)
- Track in-degree via
parent[]; each node can receive at most one parent edge. - Union-find detects cycles when linking a child already connected to its ancestor.
- Valid iff exactly one root remains and no union failed.
Time: O(n α(n)) | Space: O(n)
Problem 2: Validate Binary Search Tree (Leetcode:98)#
Problem Statement
Given the root of a binary tree, determine if it is a valid binary search tree (BST).
A valid BST is defined as follows:
Example 1:
Input: root = [2,1,3]
Output: true
Example 2:
Input: root = [5,1,4,null,null,3,6]
Output: false
Explanation:
The root node's value is 5 but its right child's value is 4.
Constraints:
- The number of nodes in the tree is in the range
[1, 104].-231 31 - 1
Code and Explanation
- Inorder traversal of a valid BST yields strictly increasing values.
- Track
prev; reject ifnode.val <= prev. - Short-circuit on first violation.
Time: O(n) | Space: O(h)
- Each node must satisfy
low < val < highfor its valid range. - Left child inherits upper bound
node.val; right child inherits lower boundnode.val. - Handles duplicate-value edge cases that break naive comparisons.
Time: O(n) | Space: O(h)
miscellaneous#
Problem 1: Flatten Binary Tree to Linked List (Leetcode:114)#
Problem Statement
Given the root of a binary tree, flatten the tree into a "linked list":
Example 1:
Input: root = [1,2,5,3,4,null,6]
Output: [1,null,2,null,3,null,4,null,5,null,6]
Example 2:
Input: root = []
Output: []
Example 3:
Input: root = [0]
Output: [0]
Constraints:
- The number of nodes in the tree is in the range
[0, 2000].-100 <= Node.val <= 100
Code and Explanation
- Process nodes in root → right → left order (reverse of desired preorder tail).
- Link each processed node to the next stack top as its right child.
- Clears left pointers to form the linked-list structure.
Time: O(n) | Space: O(h)
- Reverse postorder (right, left, node) visits nodes from tail to head of the target list.
- Attach current node in front of
prevvianode.right = prev. - Classic O(h) space recursive variant.
Time: O(n) | Space: O(h)
Problem 2: Count Complete Tree Nodes (Leetcode:222)#
Problem Statement
Given the root of a complete binary tree, return the number of the nodes in the tree.
According to Wikipedia, every level, except possibly the last, is completely filled in a complete binary tree, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
Design an algorithm that runs in less than O(n) time complexity.
Example 1:
Input: root = [1,2,3,4,5,6]
Output: 6
Example 2:
Input: root = []
Output: 0
Example 3:
Input: root = [1]
Output: 1
Constraints:
- The number of nodes in the tree is in the range
[0, 5 * 104].0 4- The tree is guaranteed to be complete.
Code and Explanation
- Straightforward recursion counts every node.
- Works on any tree shape; ignores the complete-tree property.
- Simple baseline solution.
Time: O(n) | Space: O(h)
- Compare left and right spine heights from the root's children.
- Equal heights → left subtree is a perfect tree of
2^left_hnodes; recurse only on the right. - Unequal → right subtree is perfect; recurse on the left. Exploits completeness for O(log² n).
Time: O(log² n) | Space: O(log n)
Problem 3: Maximum Width of Binary Tree (Leetcode:662)#
Problem Statement
Given the root of a binary tree, return the maximum width of the given tree.
The maximum width of a tree is the maximum width among all levels.
The width of one level is defined as the length between the end-nodes (the leftmost and rightmost non-null nodes), where the null nodes between the end-nodes that would be present in a complete binary tree extending down to that level are also counted into the length calculation.
It is guaranteed that the answer will in the range of a 32-bit signed integer.
Example 1:
Input: root = [1,3,2,5,3,null,9]
Output: 4
Explanation:
The maximum width exists in the third level with length 4 (5,3,null,9).
Example 2:
Input: root = [1,3,2,5,null,null,9,6,null,7]
Output: 7
Explanation:
The maximum width exists in the fourth level with length 7 (6,null,null,null,null,null,7).
Example 3:
Input: root = [1,3,2,5]
Output: 2
Explanation:
The maximum width exists in the second level with length 2 (3,2).
Constraints:
- The number of nodes in the tree is in the range
[1, 3000].-100 <= Node.val <= 100
Code and Explanation
- Assign each node an index as in a heap array: left
2*i, right2*i+1. - Width at a level =
last_index - first_index + 1. - BFS processes level by level, tracking the maximum width.
Time: O(n) | Space: O(w)
- DFS tracks the leftmost index seen at each depth.
- Current width at depth
d=idx - leftmost[d] + 1. - Same indexing scheme as BFS without a queue.
Time: O(n) | Space: O(h)
Problem 4: Check Completeness of a Binary Tree (Leetcode:958)#
Problem Statement
Given the root of a binary tree, determine if it is a complete binary tree.
In a complete binary tree, every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
Example 1:
Input: root = [1,2,3,4,5,6]
Output: true
Explanation:
Every level before the last is full (ie. levels with node-values {1} and {2, 3}), and all nodes in the last level ({4, 5, 6}) are as far left as possible.
Example 2:
Input: root = [1,2,3,4,5,null,7]
Output: false
Explanation:
The node with value 7 isn't as far left as possible.
Constraints:
- The number of nodes in the tree is in the range
[1, 100].1 <= Node.val <= 1000
Code and Explanation
- BFS enqueues both children (including
None) for every node. - Once a
Noneis dequeued, every subsequent node must also beNone. - Any non-null after a null means a gap — tree is incomplete.
Time: O(n) | Space: O(w)
- A complete tree with height
hhas between2^(h-1)and2^h - 1nodes. - Count nodes and height; verify the count fits the complete-tree range.
- Alternative mathematical check — BFS sentinel is more direct in interviews.
Time: O(n) | Space: O(h)
Problem 5: Cousins in Binary Tree (Leetcode:993)#
Problem Statement
Given the root of a binary tree with unique values and the values of two different nodes of the tree x and y, return true if the nodes corresponding to the values x and y in the tree are cousins, or false otherwise.
Two nodes of a binary tree are cousins if they have the same depth with different parents.
Note that in a binary tree, the root node is at the depth 0, and children of each depth k node are at the depth k + 1.
Example 1:
Input: root = [1,2,3,4], x = 4, y = 3
Output: false
Example 2:
Input: root = [1,2,3,null,4,null,5], x = 5, y = 4
Output: true
Example 3:
Input: root = [1,2,3,null,4], x = 2, y = 3
Output: false
Constraints:
- The number of nodes in the tree is in the range
[2, 100].1 <= Node.val <= 100- Each node has a unique value.
x != yxandyare exist in the tree.
Code and Explanation
- BFS level by level; record each child's parent value at the current depth.
- If both
xandyappear at the same level, they are cousins iff they have different parents. - Same parent at the same depth means siblings, not cousins.
Time: O(n) | Space: O(w)
- DFS stores
(depth, parent_val)forxandy. - Cousins share depth but have different parents.
- Compact when the tree is deep and targets are few.
Time: O(n) | Space: O(h)
Problem 6: Maximum Difference Between Node and Ancestor (Leetcode:1026)#
Problem Statement
Given the root of a binary tree, find the maximum value v for which there exist different nodes a and b where v = |a.val - b.val| and a is an ancestor of b.
A node a is an ancestor of b if either: any child of a is equal to b or any child of a is an ancestor of b.
Example 1:
Input: root = [8,3,10,1,6,null,14,null,null,4,7,13]
Output: 7
Explanation:
Explanation: We have various ancestor-node differences, some of which are given below :
|8 - 3| = 5
|3 - 7| = 4
|8 - 1| = 7
|10 - 13| = 3
Among all possible differences, the maximum value of 7 is obtained by |8 - 1| = 7.
Example 2:
Input: root = [1,null,2,null,0,3]
Output: 3
Constraints:
- The number of nodes in the tree is in the range
[2, 5000].0 5
Code and Explanation
- At each node, the max ancestor difference uses the min and max values on the root-to-node path.
- Update
resultwithnode.val - min_valandmax_val - node.val. - Pass updated min/max to children.
Time: O(n) | Space: O(h)
- Postorder returns
(subtree_min, subtree_max, best_diff)for each subtree. - At each node, compare against min/max from left and right children.
- Aggregates the global maximum bottom-up.
Time: O(n) | Space: O(h)
Problem 7: Number of Good Leaf Nodes Pairs (Leetcode:1530)#
Problem Statement
You are given the root of a binary tree and an integer distance. A pair of two different leaf nodes of a binary tree is said to be good if the length of the shortest path between them is less than or equal to distance.
Return the number of good leaf node pairs in the tree.
Example 1:
Input: root = [1,2,3,null,4], distance = 3
Output: 1
Explanation:
The leaf nodes of the tree are 3 and 4 and the length of the shortest path between them is 3. This is the only good pair.
Example 2:
Input: root = [1,2,3,4,5,6,7], distance = 3
Output: 2
Explanation:
The good pairs are [4,5] and [6,7] with shortest path = 2. The pair [4,6] is not good because the length of ther shortest path between them is 4.
Example 3:
Input: root = [7,1,4,6,null,5,3,null,null,null,null,null,2], distance = 3
Output: 1
Explanation:
The only good pair is [2,5].
Constraints:
- The number of nodes in the
treeis in the range[1, 210].1 <= Node.val <= 1001 <= distance <= 10
Code and Explanation
- Each DFS call returns distances from the current node to leaves in its subtree.
- Pair leaves from left and right subtrees whose combined path length ≤
distance. - Increment
countfor every valid cross-subtree leaf pair at each internal node.
Time: O(n · L²) where L = leaves per subtree | Space: O(h)
- Return a frequency array of leaf distances instead of a raw list.
- Cross-multiply left/right frequencies to count valid pairs in O(distance²) per node.
- More efficient when
distanceis small (≤ 10 per constraints).
Time: O(n · d²) | Space: O(n · d)
Problem 8: Smallest Subtree with all the Deepest Nodes (Leetcode:865)#
Problem Statement
Given the root of a binary tree, the depth of each node is the shortest distance to the root.
Return the smallest subtree such that it contains all the deepest nodes in the original tree.
A node is called the deepest if it has the largest depth possible among any node in the entire tree.
The subtree of a node is a tree consisting of that node, plus the set of all descendants of that node.
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4]
Output: [2,7,4]
Explanation:
We return the node with value 2, colored in yellow in the diagram.
The nodes coloured in blue are the deepest nodes of the tree.
Notice that nodes 5, 3 and 2 contain the deepest nodes in the tree but node 2 is the smallest subtree among them, so we return it.
Example 2:
Input: root = [1]
Output: [1]
Explanation:
The root is the deepest node in the tree.
Example 3:
Input: root = [0,1,3,null,2]
Output: [2]
Explanation:
The deepest node in the tree is 2, the valid subtrees are the subtrees of nodes 2, 1 and 0 but the subtree of node 2 is the smallest.
Constraints:
- The number of nodes in the tree will be in the range
[1, 500].0 <= Node.val <= 500- The values of the nodes in the tree are unique.
Code and Explanation
- Identical core logic to LCA of Deepest Leaves (LeetCode 1123).
- Return the node where left and right deepest depths meet.
- Single O(n) postorder pass.
Time: O(n) | Space: O(h)
- Pass 1: DFS collects all deepest nodes and builds a parent map.
- Pass 2: Pairwise LCA of deepest nodes yields the smallest containing subtree.
- Clearer to reason about but uses extra space.
Time: O(n) | Space: O(n)
Problem 9: All Nodes Distance K in Binary Tree (Leetcode:863)#
Problem Statement
Given the root of a binary tree, the value of a target node target, and an integer k, return an array of the values of all nodes that have a distance k from the target node.
You can return the answer in any order.
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 2
Output: [7,4,1]
Explanation:
Explanation: The nodes that are a distance 2 from the target node (with value 5) have values 7, 4, and 1.
Example 2:
Input: root = [1], target = 1, k = 3
Output: []
Constraints:
- The number of nodes in the tree is in the range
[1, 500].0 <= Node.val <= 500- All the values
Node.valare unique.targetis the value of one of the nodes in the tree.0 <= k <= 1000
Code and Explanation
- Trees lack parent pointers — build a parent map first.
- BFS from
targettreating edges as undirected (left, right, parent). - Collect values when distance equals
k.
Time: O(n) | Space: O(n)
- Build an undirected adjacency list from the tree.
- DFS from
targetoutward to distancek. - Equivalent to BFS; choose based on comfort with graphs.
Time: O(n) | Space: O(n)
Problem 10: Find a Corresponding Node of a Binary Tree in a Clone of That Tree (Leetcode:1379)#
Problem Statement
Given two binary trees original and cloned and given a reference to a node target in the original tree.
The cloned tree is a copy of the original tree.
Return a reference to the same node in the cloned tree.
Note that you are not allowed to change any of the two trees or the target node and the answer must be a reference to a node in the cloned tree.
Example 1:
Input: tree = [7,4,3,null,null,6,19], target = 3
Output: 3
Explanation:
In all examples the original and cloned trees are shown. The target node is a green node from the original tree. The answer is the yellow node from the cloned tree.
Example 2:
Input: tree = [7], target = 7
Output: 7
Example 3:
Input: tree = [8,null,6,null,5,null,4,null,3,null,2,null,1], target = 4
Output: 4
Constraints:
- The number of nodes in the
treeis in the range[1, 104].- The values of the nodes of the
treeare unique.targetnode is a node from theoriginaltree and is notnull.
Code and Explanation
- Traverse both trees in lockstep — same structure guarantees matching positions.
- Return the cloned node when the original pointer equals
target. - O(n) worst case, often faster if target is shallow.
Time: O(n) | Space: O(h)
- BFS enqueues
(original, cloned)pairs level by level. - First match on the original side returns the paired cloned node.
- Same logic as DFS; useful when recursion depth is a concern.
Time: O(n) | Space: O(w)
Problem 11: All Possible Full Binary Trees (Leetcode:894)#
Problem Statement
Given an integer n, return a list of all possible full binary trees with n nodes. Each node of each tree in the answer must have Node.val == 0.
Each element of the answer is the root node of one possible tree. You may return the final list of trees in any order.
A full binary tree is a binary tree where each node has exactly 0 or 2 children.
Example 1:
Input: n = 7
Output: [[0,0,0,null,null,0,0,null,null,0,0],[0,0,0,null,null,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,null,null,null,null,0,0],[0,0,0,0,0,null,null,0,0]]
Example 2:
Input: n = 3
Output: [[0,0,0]]
Constraints:
1 <= n <= 20
Code and Explanation
- A full binary tree with
nnodes exists only when n is odd. - Split
n-1remaining nodes into oddleft_countandright_count; combine all pairs. - Memoize subproblem results to avoid rebuilding identical subtrees.
Time: O(2^n) output size | Space: O(n)
- Fill
dp[count]for odd counts from 3 ton. - Same split-and-combine logic as recursion, but iterative tabulation.
- Avoids recursion depth and repeated memo lookups.
Time: O(2^n) | Space: O(n)
Problem 12: Delete Leaves With a Given Value (Leetcode:1325)#
Problem Statement
Given a binary tree root and an integer target, delete all the leaf nodes with value target.
Note that once you delete a leaf node with value target, if its parent node becomes a leaf node and has the value target, it should also be deleted (you need to continue doing that until you cannot).
Example 1:
Input: root = [1,2,3,2,null,2,4], target = 2
Output: [1,null,3,null,4]
Explanation:
Leaf nodes in green with value (target = 2) are removed (Picture in left).
After removing, new nodes become leaf nodes with value (target = 2) (Picture in center).
Example 2:
Input: root = [1,3,3,3,2], target = 3
Output: [1,3,null,null,2]
Example 3:
Input: root = [1,2,null,2,null,2], target = 2
Output: [1]
Explanation:
Leaf nodes in green with value (target = 2) are removed at each step.
Constraints:
- The number of nodes in the tree is in the range
[1, 3000].1 <= Node.val, target <= 1000
Code and Explanation
- Postorder: process children before the parent so leaves are identified correctly.
- After pruning children, if the current node is a matching leaf, return
None. - Repeated passes happen naturally as parents become new leaves.
Time: O(n) | Space: O(h)
- Explicit postorder stack processes leaves before their parents.
- Detach matching leaves from the parent pointer.
- Mirrors the recursive solution without call-stack depth limits.
Time: O(n) | Space: O(h)
Problem 13: Delete Nodes And Return Forest (Leetcode:1110)#
Problem Statement
Given the root of a binary tree, each node in the tree has a distinct value.
After deleting all nodes with a value in to_delete, we are left with a forest (a disjoint union of trees).
Return the roots of the trees in the remaining forest. You may return the result in any order.
Example 1:
Input: root = [1,2,3,4,5,6,7], to_delete = [3,5]
Output: [[1,2,null,4],[6],[7]]
Example 2:
Input: root = [1,2,4,null,3], to_delete = [3]
Output: [[1,2,4]]
Constraints:
- The number of nodes in the given tree is at most
1000.- Each node has a distinct value between
1and1000.to_delete.length <= 1000to_deletecontains distinct values between1and1000.
Code and Explanation
- A node becomes a new forest root if it is not deleted and its parent was deleted (or it is the original root).
- Postorder removes deleted nodes by returning
Noneto the parent. - Children of deleted nodes are re-entered DFS with
is_root=True.
Time: O(n) | Space: O(h + |to_delete|)
- BFS builds parent pointers, then scan all nodes.
- Non-deleted nodes whose parent is deleted (or absent) join the forest.
- Detach deleted nodes from their parents explicitly.
Time: O(n) | Space: O(n)
Problem 14: Find Duplicate Subtrees (Leetcode:652)#
Problem Statement
Given the root of a binary tree, return all duplicate subtrees.
For each kind of duplicate subtrees, you only need to return the root node of any one of them.
Two trees are duplicate if they have the same structure with the same node values.
Example 1:
Input: root = [1,2,3,4,null,2,4,null,null,4]
Output: [[2,4],[4]]
Example 2:
Input: root = [2,1,1]
Output: [[1]]
Example 3:
Input: root = [2,2,2,3,null,3,null]
Output: [[2,3],[3]]
Constraints:
- The number of the nodes in the tree will be in the range
[1, 5000]-200 <= Node.val <= 200
Code and Explanation
- Serialize each subtree as
val,left,rightstring keys. - Increment a counter; on the second occurrence, add the subtree root to results.
- Postorder ensures children are serialized before the parent.
Time: O(n²) string building | Space: O(n²)
- Assign each unique subtree shape an integer ID via
(val, left_id, right_id)triplets. - Avoids long string concatenation — more efficient for large trees.
- Still postorder; duplicate detection on second ID occurrence.
Time: O(n) | Space: O(n)
Problem 15: House Robber III (Leetcode:337)#
Problem Statement
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called root.
Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that all houses in this place form a binary tree. It will automatically contact the police if two directly-linked houses were broken into on the same night.
Given the root of the binary tree, return the maximum amount of money the thief can rob without alerting the police**.
Example 1:
Input: root = [3,2,3,null,3,null,1]
Output: 7
Explanation:
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
Input: root = [3,4,5,1,3,null,1]
Output: 9
Explanation:
Maximum amount of money the thief can rob = 4 + 5 = 9.
Constraints:
- The number of nodes in the tree is in the range
[1, 104].0 4
Code and Explanation
- Return
(rob_current, skip_current)for each subtree. - Rob = node value + best skip values from children (cannot rob adjacent nodes).
- Skip = sum of max(rob, skip) from each child. Answer is
maxat the root.
Time: O(n) | Space: O(h)
- Alternative recurrence: robbing a node skips its children but includes grandchildren.
- Memoize per-node results to avoid recomputation in the naive recursion.
- Same optimal answer; tuple approach is cleaner for trees.
Time: O(n) | Space: O(n)
Problem 16: Step-By-Step Directions From a Binary Tree Node to Another (Leetcode:2096)#
Problem Statement
You are given the root of a binary tree with n nodes. Each node is uniquely assigned a value from 1 to n. You are also given an integer startValue representing the value of the start node s, and a different integer destValue representing the value of the destination node t.
Find the shortest path starting from node s and ending at node t. Generate step-by-step directions of such path as a string consisting of only the uppercase letters 'L', 'R', and 'U'. Each letter indicates a specific direction:
Return the step-by-step directions of the shortest path from node s to node t.
Example 1:
Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6
Output: "UURL"
Explanation:
The shortest path is: 3 → 1 → 5 → 2 → 6.
Example 2:
Input: root = [2,1], startValue = 2, destValue = 1
Output: "L"
Explanation:
The shortest path is: 2 → 1.
Constraints:
- The number of nodes in the tree is
n.2 51 <= Node.val <= n- All the values in the tree are unique.
1 <= startValue, destValue <= nstartValue != destValue
Code and Explanation
- Build root-to-node paths for start and dest as
L/Rstrings. - Strip the common prefix — that shared path ends at the LCA.
- Go up from start (
Urepeated) then follow the remaining dest path.
Time: O(n) | Space: O(n)
- Build parent map, climb from
starttowarddestrecordingUsteps. - Trace
L/Rfrom LCA down todest. - Equivalent path logic using explicit parent pointers.
Time: O(n) | Space: O(n)
Problem 17: Populating Next Right Pointers in Each Node II (Leetcode:117)#
Problem Statement
Given a binary tree
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
Example 1:
Input: root = [1,2,3,4,5,null,7]
Output: [1,#,2,3,#,4,5,7,#]
Explanation:
Explanation: Given the above binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.
Example 2:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 6000].-100 <= Node.val <= 100
Code and Explanation
- BFS processes each level; link each node to the next queue front.
- Last node at each level has
next = Noneimplicitly. - O(n) time; uses O(w) extra space for the queue.
Time: O(n) | Space: O(w)
- Use the already-linked next pointers to traverse the current level.
- Build the next level's linked list with a dummy head (
tailpointer). - O(1) extra space — optimal for follow-up constraints.
Time: O(n) | Space: O(1)
Problem 18: Distribute Coins in Binary Tree (Leetcode:979)#
Problem Statement
You are given the root of a binary tree with n nodes where each node in the tree has node.val coins. There are n coins in total throughout the whole tree.
In one move, we may choose two adjacent nodes and move one coin from one node to another. A move may be from parent to child, or from child to parent.
Return the minimum number of moves required to make every node have exactly one coin.
Example 1:
Input: root = [3,0,0]
Output: 2
Explanation:
Explanation: From the root of the tree, we move one coin to its left child, and one coin to its right child.
Example 2:
Input: root = [0,3,0]
Output: 3
Explanation:
Explanation: From the left child of the root, we move two coins to the root [taking two moves]. Then, we move one coin from the root of the tree to the right child.
Constraints:
- The number of nodes in the tree is
n.1 <= n <= 1000 <= Node.val <= n- The sum of all
Node.valisn.
Code and Explanation
- Each subtree returns excess coins (positive = surplus, negative = deficit).
- Moving
|excess|coins across an edge costs that many moves. - Sum absolute excess flows from children at every node.
Time: O(n) | Space: O(h)
- Same excess-flow logic with an explicit postorder stack.
- Store subtree excess in a hash map; accumulate moves on node completion.
- Avoids recursion on very deep trees.
Time: O(n) | Space: O(n)
Problem 19: Serialize and Deserialize Binary Tree (Leetcode:297)#
Problem Statement
Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Example 1:
Input: root = [1,2,3,null,null,4,5]
Output: [1,2,3,null,null,4,5]
Example 2:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 104].-1000 <= Node.val <= 1000
Code and Explanation
- BFS encodes nodes level by level, using
"null"for missing children. - Deserialize reads values in the same order, attaching left then right children.
- Compact and matches LeetCode's array representation.
Time: O(n) serialize & deserialize | Space: O(n)
- Preorder DFS with
"null"markers uniquely defines tree structure. - Deserialize consumes tokens in the same preorder sequence.
- Often shorter strings than BFS for sparse trees.
Time: O(n) | Space: O(n)
Problem 20: Binary Tree Cameras (Leetcode:968)#
Problem Statement
You are given the root of a binary tree. We install cameras on the tree nodes where each camera at a node can monitor its parent, itself, and its immediate children.
Return the minimum number of cameras needed to monitor all nodes of the tree.
Example 1:
Input: root = [0,0,null,0,0]
Output: 1
Explanation:
One camera is enough to monitor all nodes if placed as shown.
Example 2:
Input: root = [0,0,null,0,null,0,null,null,0]
Output: 2
Explanation:
At least two cameras are needed to monitor all nodes of the tree. The above image shows one of the valid configurations of camera placement.
Constraints:
- The number of nodes in the tree is in the range
[1, 1000].Node.val == 0
Code and Explanation
- States: 0 = uncovered, 1 = has camera, 2 = covered (no camera).
- If any child is uncovered (
0), place a camera at the current node. - If any child has a camera (
1), current node is covered. Add a root camera if the root remains uncovered.
Time: O(n) | Space: O(h)
- Each node tracks three costs: camera here, covered without camera, uncovered.
- Combine child states to minimize cameras bottom-up.
- More verbose than the greedy state machine but illustrates tree DP thinking.
Time: O(n) | Space: O(h)






































































