Given the root
of a binary tree, return the most frequent subtree sum. If there is a tie, return all the values with the highest frequency in any order.
The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself).
For example:
Consider the following binary tree:
5
/ \
2 -3
The subtree sums are:
The frequencies are:
Since 2, -3, and 4 all have a frequency of 1, the output should be [2, -3, 4]
.
As another example:
5
/ \
2 -5
The subtree sums are:
The frequencies are:
Since 2 has the highest frequency (2), the output should be [2]
.
Write a function that takes the root of a binary tree as input and returns an array containing the most frequent subtree sums. If there is a tie, return all values with the highest frequency in any order.
Constraints:
[1, 10^4]
.-10^5 <= Node.val <= 10^5
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To find the most frequent subtree sum, we'll calculate the sum of every possible subtree. Then, we'll count how many times each sum appears, and find the sum that appears most often.
Here's how the algorithm would work step-by-step:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def find_most_frequent_subtree_sum_brute_force(root):
subtree_sums = []
def calculate_subtree_sum(node):
if not node:
return 0
# Recursively calculate sums of left and right subtrees
left_subtree_sum = calculate_subtree_sum(node.left)
right_subtree_sum = calculate_subtree_sum(node.right)
subtree_sum = node.val + left_subtree_sum + right_subtree_sum
subtree_sums.append(subtree_sum)
return subtree_sum
calculate_subtree_sum(root)
sum_frequency = {}
# Count the frequency of each subtree sum
for subtree_sum in subtree_sums:
if subtree_sum in sum_frequency:
sum_frequency[subtree_sum] += 1
else:
sum_frequency[subtree_sum] = 1
max_frequency = 0
most_frequent_sums = []
# Find the sums with the highest frequency
for subtree_sum, frequency in sum_frequency.items():
if frequency > max_frequency:
max_frequency = frequency
most_frequent_sums = [subtree_sum]
elif frequency == max_frequency:
most_frequent_sums.append(subtree_sum)
return most_frequent_sums
To find the most frequent subtree sum efficiently, we calculate the sum of each subtree only once using a clever trick that builds up from the bottom. We keep track of how often each sum appears and then find the sum that occurred most often.
Here's how the algorithm would work step-by-step:
def find_most_frequent_subtree_sum(root):
subtree_sums = {}
most_frequent_sums = []
max_frequency = 0
def calculate_subtree_sum(node):
if not node:
return 0
left_subtree_sum = calculate_subtree_sum(node.left)
right_subtree_sum = calculate_subtree_sum(node.right)
current_subtree_sum = node.val + left_subtree_sum + right_subtree_sum
# Store and count each subtree sum encountered
if current_subtree_sum not in subtree_sums:
subtree_sums[current_subtree_sum] = 0
subtree_sums[current_subtree_sum] += 1
return current_subtree_sum
calculate_subtree_sum(root)
# Iterate through the sums to find the most frequent ones.
for subtree_sum, frequency in subtree_sums.items():
if frequency > max_frequency:
# New max, reset list
most_frequent_sums = [subtree_sum]
max_frequency = frequency
elif frequency == max_frequency:
# Another sum with the same max frequency
most_frequent_sums.append(subtree_sum)
return most_frequent_sums
Case | How to Handle |
---|---|
Null root node | Return an empty list if the root is null as there are no subtrees. |
Single node tree | Return a list containing the value of the single node as the only subtree sum. |
All nodes have the same value (e.g., all 0s or all 1s) | The frequency map will have a single entry and return a list with that value. |
Large tree causing deep recursion leading to stack overflow | Ensure the recursion depth is within limits or convert to an iterative approach using a stack. |
Integer overflow in subtree sum calculation | Use a larger data type like long to store the subtree sums to prevent overflow. |
Tree with only positive node values | The sums will be positive, and the frequency map will handle the counting correctly. |
Tree with only negative node values | The sums will be negative, and the frequency map will handle the counting correctly. |
Multiple subtree sums with the same highest frequency | Return all the subtree sums that have the maximum frequency in any order. |