#3331

Find Subtree Sizes After Changes

Medium
ArrayHash TableStringTreeDepth-First SearchHash MapArray
LeetCode ↗

Approaches

Brute ForceOptimal
Complexity Comparison
Brute ForceOptimal Solution
Time
O(n²)
O(n)
Space
O(1)
O(n)
💡

Intuition

Time O(n)Space O(n)

This approach uses a depth-first search (DFS) to traverse the tree while keeping track of the most recent ancestor for each character. This allows us to efficiently find the closest ancestor with the same character without redundant checks.

⚙️

Algorithm

3 steps
  1. 1Step 1: Initialize a map to store the most recent node for each character as we perform DFS.
  2. 2Step 2: During DFS, for each node, check if the character has been seen before. If so, update its parent accordingly.
  3. 3Step 3: After making all parent changes, perform another DFS to calculate the size of the subtree for each node.
solution.py38 lines
1def findSubtreeSizes(parent, s):
2    n = len(parent)
3    new_parent = parent[:]
4    last_seen = {}
5    def dfs(node):
6        nonlocal last_seen
7
8        # Save the current character and its node
9        char = s[node]
10        prev = last_seen.get(char, -1)
11
12        # Update the last seen character
13        last_seen[char] = node
14
15        for child in range(n):
16            if parent[child] == node:
17                # If the child has the same character, update its parent
18                if s[child] == char:
19                    new_parent[child] = prev if prev != -1 else node
20                dfs(child)
21
22        # Restore the last seen character
23        if prev != -1:
24            last_seen[char] = prev
25        else:
26            del last_seen[char]
27
28    dfs(0)
29    subtree_size = [0] * n
30    def calculate_size(node):
31        size = 1
32        for child in range(n):
33            if new_parent[child] == node:
34                size += calculate_size(child)
35        subtree_size[node] = size
36        return size
37    calculate_size(0)
38    return subtree_size

Complexity note: The time complexity is O(n) because we traverse each node once during the DFS, and we use a map to store the last seen nodes for each character, which takes linear space.

  • 1Understanding tree traversal is crucial for solving problems involving parent-child relationships.
  • 2Using a map to track the last seen nodes for characters can significantly reduce the complexity of finding ancestors.

Solutions and explanations are original Tejav content. Problem titles © LeetCode — use the LeetCode button above for the full problem statement.