Before attempting this problem, you should be comfortable with:
The root of a tree is the only node that is never a child of any other node. By collecting all child nodes into a set, we can identify the root as the node whose value does not appear in the set. Every non-root node will appear exactly once as someone's child, but the root never will.
seen set.class Solution:
def findRoot(self, tree: List['Node']) -> 'Node':
# set that contains all the child nodes.
seen = set()
# add all the child nodes into the set
for node in tree:
for child in node.children:
# we could either add the value or the node itself.
seen.add(child.val)
# find the node that is not in the child node set.
for node in tree:
if node.val not in seen:
return nodeWhere is the length of the input list, which is also the number of nodes in the N-ary tree.
Every node except the root appears exactly once as a parent and exactly once as a child. If we add each node's value as a parent and subtract each child's value, all non-root nodes will cancel out (added once, subtracted once). The root is only added as a parent but never subtracted as a child, so the final sum equals the root's value.
valueSum = 0.valueSum (counting it as a parent).valueSum (counting it as a child).valueSum.class Solution:
def findRoot(self, tree: List['Node']) -> 'Node':
value_sum = 0
for node in tree:
# the value is added as a parent node
value_sum += node.val
for child in node.children:
# the value is deducted as a child node.
value_sum -= child.val
# the value of the root node is `value_sum`
for node in tree:
if node.val == value_sum:
return nodeWhere is the length of the input list, which is also the number of nodes in the N-ary tree.
When building the set of child nodes, you can store either the node's value or the node reference itself. However, be consistent. If you store values, compare values when finding the root. If you store references, compare references. Mixing the two leads to incorrect results.
The input list contains nodes in arbitrary order, not level-order or any specific traversal order. Never assume the root appears first in the list. Always iterate through all nodes to identify which one is not a child of any other.
When using the O(1) space solution that adds parent values and subtracts child values, be aware of potential integer overflow for very large trees with large node values. In languages with fixed-size integers, the sum could overflow before the final cancellation produces the correct root value.