Understand what the interviewer is asking for by using test cases and questions about the problem.
- Established a set (2-3) of test cases to verify their own solution later.
- Established a set (1-2) of edge cases to verify their solution handles complexities.
- Have fully understood the problem and have no clarifying questions.
- Have you verified any Time/Space Constraints for this problem?
HAPPY CASE
Input:
1
/ \
3 2
/ \ \
5 3 9
Output: [1, 3, 9]
Input:
-1
/ \
3 2
/ /
5 2
Output: [-1, 3, 5]
EDGE CASE
Input:
Output: []
Input: 0
Output: [0]
Input: 1
Output: [1]
Match what this problem looks like to known categories of problems, e.g. Linked List or Dynamic Programming, and strategies or patterns in those categories.
For trees, some things we should consider are:
Plan the solution with appropriate visualizations and pseudocode.
Perform a level-order traversal of the tree with a Queue. Calculate a running max while traversing the row.
1) Create a Queue and place the root in there
2) While the Queue is not empty, iterate through the queue
a) Compute the length of the Queue and iterate that fixed amount (k)
for the current row
i) Keep a running max for the row
ii) Add the left and right sub-tree nodes to the end of the queue for the
next iteration
b) Append this row's max to an output array
3) Return the array of row-wise maximums
⚠️ Common Mistakes
Implement the code to solve the algorithm.
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null) {
return result;
}
search(root, 0, result);
return result;
}
public static void search(TreeNode root, int depth, List<Integer> result) {
if (root == null) {
return;
}
if (depth >= result.size()) { // if this row of the tree has not been visited yet
result.add(root.val); // add the value
} else { // if this row has been visited already
int cur = result.get(depth); // get the previous max value of the row
int big = Math.max(cur, root.val); // compare
if (cur != big) { // if the node we are visiting now has the max value
result.remove(depth); // remove the previous
result.add(depth, big); // add the max
}
}
search(root.left, depth+1, result); // search left and right (the order does not matter)
search(root.right, depth+1, result);
}
}
import sys, queue
def largestValues(self, root: TreeNode) -> List[int]:
if not root:
return []
output = []
q = queue.Queue()
q.put(root)
while q.qsize() > 0:
cur_max = -sys.maxsize # running max value for this row
for _ in range(q.qsize()): # fixed size iteration for this row
node = q.get()
cur_max = max(cur_max, node.val)
if node.left:
q.put(node.left)
if node.right:
q.put(node.right)
output.append(cur_max)
return output
Review the code by running specific example(s) and recording values (watchlist) of your code's variables along the way.
Evaluate the performance of your algorithm and state any strong/weak or future potential work.
Assume N
represents the number of nodes in the tree.