class TreeNode:
def __init__(self, val):
self.val = val
self.children = []
def find_root(nodes):
# Root is node not child of any
all_nodes = set(nodes)
child_nodes = set(c for node in nodes for c in node.children)
roots = all_nodes - child_nodes
return roots.pop() if roots else None
def find_leaves(nodes):
# Leaves have no children
return [node for node in nodes if not node.children]
def calculate_depths(root):
depths = {}
def dfs(node, depth):
depths[node.val] = depth
for child in node.children:
dfs(child, depth + 1)
dfs(root, 0)
return depths
def calculate_height(root):
if not root.children:
return 0
return 1 + max(calculate_height(child) for child in root.children)
def group_by_level(depths):
levels = {}
for node_val, depth in depths.items():
levels.setdefault(depth, []).append(node_val)
return levels
# Build tree nodes
node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
# Connect nodes
node1.children = [node2, node3]
node2.children = [node4]
nodes = [node1, node2, node3, node4]
root = find_root(nodes)
leaves = find_leaves(nodes)
depths = calculate_depths(root)
height = calculate_height(root)
levels = group_by_level(depths)
print(f"Root: {root.val}")
print("Leaves:", ", ".join(str(n.val) for n in leaves))
print(f"Height: {height}")
print("Depths:", ", ".join(f"{k}={v}" for k,v in sorted(depths.items())))
print("Levels:")
for level in sorted(levels):
print(f" Level {level}: {', '.join(str(n) for n in sorted(levels[level]))}")roots = all_nodes - child_nodes
find node that is not child of any node -- identifies root
return [node for node in nodes if not node.children]
collect nodes with no children -- these are leaves
record depth of current node during DFS traversal
return 1 + max(calculate_height(child) for child in root.children)
height is 1 plus max height among children
levels.setdefault(depth, []).append(node_val)
group nodes by their depth into levels
Root: 1
Leaves: 3, 4
Height: 2
Depths: 1=0, 2=1, 3=1, 4=2
Levels:
Level 0: 1
Level 1: 2, 3
Level 2: 4