Find Largest Value in Each Tree Row
MedPrompt
Given the root of a binary tree, return an array of the largest value in each row of the tree (0-indexed).
Example 1:
Input: root = [1,3,2,5,3,null,9]
Output: [1,3,9]Example 2:
Input: root = [1,2,3]
Output: [1,3]
Constraints:
- The number of nodes in the tree will be in the range
[0, 104]. -231 <= Node.val <= 231 - 1
Approaches
2 approaches with complexity analysis and trade-offs.
This approach traverses the tree level by level using a queue. For each level, it iterates through all the nodes at that level to find the maximum value, then adds it to the result list. This is a very intuitive method for problems involving tree levels.
Algorithm
- Initialize an empty list
result. - If the
rootis null, return the empty list. - Create a
Queueand add therootnode. - While the queue is not empty:
- Get the number of nodes in the current level,
levelSize = queue.size(). - Initialize a variable
maxInLeveltoInteger.MIN_VALUE. - Loop
levelSizetimes:- Dequeue a node
currentNode. - Update
maxInLevelwith the maximum of its current value andcurrentNode.val. - Enqueue the left and right children of
currentNodeif they are not null.
- Dequeue a node
- Add
maxInLevelto theresultlist.
- Get the number of nodes in the current level,
- Return
result.
Walkthrough
We can solve this problem by performing a level order traversal of the tree, which is naturally implemented using a Breadth-First Search (BFS) algorithm with a queue.
The core idea is to process the tree one level at a time. We start by putting the root node in a queue. Then, we enter a loop that continues as long as the queue is not empty. In each iteration of this outer loop, we are processing a single level. We first determine the number of nodes on the current level by checking the queue's size. We then iterate exactly that many times, dequeueing one node at a time. While processing the nodes of a level, we keep track of the maximum value seen so far. After the inner loop finishes, we have the largest value for that level, which we add to our result list. We also add the children of each processed node to the queue, which sets up the next level for the subsequent iteration of the outer loop.
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */class Solution { public List<Integer> largestValues(TreeNode root) { List<Integer> result = new ArrayList<>(); if (root == null) { return result; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { int levelSize = queue.size(); int maxInLevel = Integer.MIN_VALUE; for (int i = 0; i < levelSize; i++) { TreeNode currentNode = queue.poll(); maxInLevel = Math.max(maxInLevel, currentNode.val); if (currentNode.left != null) { queue.offer(currentNode.left); } if (currentNode.right != null) { queue.offer(currentNode.right); } } result.add(maxInLevel); } return result; }}Complexity
Time
O(N), where N is the total number of nodes in the tree. Each node is visited, enqueued, and dequeued exactly once.
Space
O(W), where W is the maximum width of the tree. In the worst-case scenario of a complete binary tree, the width can be up to N/2, leading to a space complexity of O(N).
Trade-offs
Pros
Very intuitive for level-by-level tree problems.
Iterative approach avoids recursion depth limits and potential stack overflow on very deep trees.
Cons
Can be less space-efficient than DFS for wide trees (e.g., complete binary trees), as the queue can hold up to O(N) nodes.
Solutions
Solution
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */ class Solution { public List < Integer > largestValues ( TreeNode root ) { List < Integer > ans = new ArrayList <>(); if ( root == null ) { return ans ; } Deque < TreeNode > q = new ArrayDeque <>(); q . offer ( root ); while (! q . isEmpty ()) { int t = q . peek (). val ; for ( int i = q . size (); i > 0 ; -- i ) { TreeNode node = q . poll (); t = Math . max ( t , node . val ); if ( node . left != null ) { q . offer ( node . left ); } if ( node . right != null ) { q . offer ( node . right ); } } ans . add ( t ); } return ans ; } }Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.