Facebook Pixel

2322. Minimum Score After Removals on a Tree

Problem Description

You are given an undirected connected tree with n nodes labeled from 0 to n - 1 and n - 1 edges. Each node i has a value nums[i], and the edges are represented as a 2D array where edges[i] = [ai, bi] indicates an edge between nodes ai and bi.

Your task is to remove two distinct edges from the tree, which will split it into three connected components. For each pair of removed edges, you need to:

  1. Calculate the XOR of all node values in each of the three components
  2. Find the difference between the largest and smallest XOR values among the three components - this is the "score" for that pair of removed edges

For example, if after removing two edges you get three components with node values [4,5,7], [1,9], and [3,3,3]:

  • Component 1 XOR: 4 ^ 5 ^ 7 = 6
  • Component 2 XOR: 1 ^ 9 = 8
  • Component 3 XOR: 3 ^ 3 ^ 3 = 3
  • The score would be 8 - 3 = 5 (largest XOR minus smallest XOR)

You need to find and return the minimum possible score among all valid pairs of edge removals.

The solution uses DFS to explore different ways of removing edges. It first calculates the total XOR sum s of all nodes. Then for each possible first edge removal (creating two components with XOR sums s1 and s ^ s1), it explores removing a second edge within one component. This creates three components with XOR sums: s ^ s1, s2, and s1 ^ s2. The algorithm tracks the minimum difference between the maximum and minimum XOR values across all possible edge removal combinations.

Flowchart Walkthrough

First, let's pin down the algorithm using the Flowchart. Here's a step-by-step walkthrough:

Is it a graph?

  • Yes: The problem explicitly involves an undirected connected tree with nodes and edges. A tree is a special type of graph.

Is it a tree?

  • Yes: The problem states we have an undirected connected tree with n nodes and n-1 edges, which is the definition of a tree.

DFS

  • Since we're dealing with a tree structure, the flowchart leads us directly to DFS (Depth-First Search).

Conclusion: The flowchart suggests using DFS for this tree problem.

Why DFS is the Right Choice

The problem requires us to:

  1. Remove two edges to create three connected components
  2. Calculate XOR sums for each component
  3. Find the minimum score across all possible edge removal combinations

DFS is perfectly suited for this because:

  • We need to traverse the tree to calculate subtree XOR sums
  • DFS allows us to efficiently compute XOR values for subtrees rooted at different nodes
  • When we remove an edge, DFS helps us explore the resulting components and calculate their respective XOR sums
  • The recursive nature of DFS naturally handles the tree structure and allows us to accumulate XOR values from child nodes to parent nodes

The solution uses DFS twice:

  1. First DFS (dfs): Calculates the XOR sum of a subtree after removing the first edge
  2. Second DFS (dfs2): Explores removing a second edge within the remaining component and calculates the resulting three XOR sums
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

When we remove two edges from a tree, we split it into exactly three connected components. The key insight is that we need to systematically explore all possible ways to remove two edges and track the resulting XOR values.

Let's think about what happens when we remove edges. If we remove edge (u, v), we split the tree into two parts. If we then remove another edge from one of these parts, we get three components total. The challenge is computing the XOR sum for each component efficiently.

The first observation is that XOR has a useful property: a ^ a = 0. This means if we know the total XOR sum s of all nodes and the XOR sum s1 of one component, we can get the XOR sum of the remaining part as s ^ s1.

Here's the strategy that emerges:

  1. First, calculate the total XOR sum s of all node values in the tree
  2. For each possible first edge to remove, we get two components - one with XOR sum s1 and the other with XOR sum s ^ s1
  3. Within the component with XOR sum s1, we explore removing a second edge, which creates a sub-component with XOR sum s2
  4. This gives us three components with XOR sums: s ^ s1 (the untouched component), s2 (the sub-component), and s1 ^ s2 (the remainder after removing s2 from s1)

The beauty of using DFS is that it naturally computes subtree XOR sums. When we do DFS from a node, we can accumulate the XOR values from all its descendants. By treating each edge as a potential cut point and using the parent-child relationship in DFS traversal, we can efficiently enumerate all possible ways to remove two edges.

We need two DFS functions: one to compute the XOR sum after the first edge removal, and another to explore all possible second edge removals within that component while keeping track of the minimum score.

Learn more about Tree and Depth-First Search patterns.

Solution Approach

The implementation uses two DFS functions to systematically explore all possible ways of removing two edges from the tree.

Step 1: Build the Graph Representation We first construct an adjacency list g using a defaultdict(list) to represent the tree structure. Each edge [a, b] creates bidirectional connections.

Step 2: Calculate Total XOR Sum We compute s, the XOR sum of all node values using reduce(lambda x, y: x ^ y, nums). This gives us the baseline XOR value for the entire tree.

Step 3: First DFS Function - dfs(i, fa) This function calculates the XOR sum of a subtree rooted at node i, where fa is the parent node (to avoid revisiting):

  • Start with res = nums[i] (the node's own value)
  • For each child j of node i (excluding parent fa), recursively compute and XOR the subtree values
  • Return the accumulated XOR sum for this subtree

Step 4: Second DFS Function - dfs2(i, fa) This function explores removing a second edge within the subtree and calculates the minimum score:

  • Similar to dfs, it computes the XOR sum of the subtree rooted at i
  • For each child j, it gets the XOR sum s2 of that child's subtree
  • With s2 known, we now have three components:
    • Component 1: s ^ s1 (everything outside the first cut)
    • Component 2: s2 (the subtree below the second cut)
    • Component 3: s1 ^ s2 (remainder after removing s2 from s1)
  • Calculate mx = max(s ^ s1, s2, s1 ^ s2) and mn = min(s ^ s1, s2, s1 ^ s2)
  • Update the global minimum: ans = min(ans, mx - mn)

Step 5: Main Loop - Enumerate All First Cuts For each node i and each of its neighbors j:

  • Treat the edge (i, j) as the first edge to remove
  • Calculate s1 = dfs(i, j) - the XOR sum of the component containing node i after removing edge (i, j)
  • Call dfs2(i, j) to explore all possible second edge removals within this component

The algorithm leverages the XOR properties and tree structure to efficiently compute all possible three-way partitions. By systematically trying each edge as the first cut and then exploring second cuts within the resulting components, we ensure we find the minimum possible score.

The time complexity is O(n²) where n is the number of nodes, as we potentially explore each edge as both first and second cut. The space complexity is O(n) for the recursion stack and adjacency list storage.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example to illustrate the solution approach.

Consider a tree with 5 nodes where:

  • nums = [6, 4, 2, 3, 5] (node values)
  • edges = [[0,1], [1,2], [1,3], [3,4]]

The tree structure looks like:

      0(6)
       |
      1(4)
     / | \
   2(2) 3(3)
         |
        4(5)

Step 1: Calculate Total XOR Sum s = 6 ^ 4 ^ 2 ^ 3 ^ 5 = 0

Step 2: Try First Edge Removal - Edge (1,3) Let's remove edge (1,3) as our first cut. This splits the tree into:

  • Component A: nodes {0,1,2}
  • Component B: nodes {3,4}

Calculate s1 (XOR of Component A containing node 1):

  • dfs(1, 3) computes: 4 ^ 6 ^ 2 = 0
  • So s1 = 0
  • The other component has XOR: s ^ s1 = 0 ^ 0 = 0

Step 3: Explore Second Edge Removals within Component A Now we call dfs2(1, 3) to try removing a second edge within Component A.

When exploring edge (0,1) as the second cut:

  • s2 = dfs(0, 1) = 6 (just node 0)
  • Three components now have XOR values:
    • Component 1: s ^ s1 = 0 (nodes {3,4})
    • Component 2: s2 = 6 (node {0})
    • Component 3: s1 ^ s2 = 0 ^ 6 = 6 (nodes {1,2})
  • Score: max(0, 6, 6) - min(0, 6, 6) = 6 - 0 = 6

When exploring edge (1,2) as the second cut:

  • s2 = dfs(2, 1) = 2 (just node 2)
  • Three components:
    • Component 1: s ^ s1 = 0 (nodes {3,4})
    • Component 2: s2 = 2 (node {2})
    • Component 3: s1 ^ s2 = 0 ^ 2 = 2 (nodes {0,1})
  • Score: max(0, 2, 2) - min(0, 2, 2) = 2 - 0 = 2

Step 4: Try Other First Edge Removals We repeat this process for all other edges as potential first cuts:

When first removing edge (3,4):

  • s1 = dfs(3, 4) = 6 ^ 4 ^ 2 ^ 3 = 3
  • Then exploring second cuts within this component gives various scores

When first removing edge (0,1):

  • s1 = dfs(0, 1) = 6
  • Component B has XOR: 0 ^ 6 = 6
  • Then exploring second cuts in Component B (which has nodes {1,2,3,4})

Step 5: Find Minimum Score After trying all possible pairs of edge removals, we track the minimum score encountered. In this example, one optimal solution might be removing edges (1,3) and (1,2), giving us a score of 2.

The algorithm systematically explores all O(n²) possible pairs of edge removals, using the XOR properties to efficiently compute component values and find the minimum possible score.

Solution Implementation

1class Solution:
2    def minimumScore(self, nums: List[int], edges: List[List[int]]) -> int:
3        from collections import defaultdict
4        from functools import reduce
5      
6        def calculate_subtree_xor(node: int, parent: int) -> int:
7            """
8            Calculate XOR of all values in subtree rooted at 'node'.
9          
10            Args:
11                node: Current node being processed
12                parent: Parent node to avoid revisiting
13          
14            Returns:
15                XOR value of the subtree
16            """
17            xor_result = nums[node]
18            for neighbor in graph[node]:
19                if neighbor != parent:
20                    xor_result ^= calculate_subtree_xor(neighbor, node)
21            return xor_result
22      
23        def find_minimum_score(node: int, parent: int) -> int:
24            """
25            Traverse tree and calculate minimum score for all possible second edge removals.
26          
27            Args:
28                node: Current node being processed
29                parent: Parent node to avoid revisiting
30          
31            Returns:
32                XOR value of the subtree rooted at 'node'
33            """
34            nonlocal total_xor, first_subtree_xor, min_score
35          
36            subtree_xor = nums[node]
37            for neighbor in graph[node]:
38                if neighbor != parent:
39                    # Calculate XOR for subtree rooted at 'neighbor'
40                    second_subtree_xor = find_minimum_score(neighbor, node)
41                    subtree_xor ^= second_subtree_xor
42                  
43                    # Calculate XOR values for three components after removing two edges
44                    # Component 1: first_subtree_xor (from first edge removal)
45                    # Component 2: second_subtree_xor (from second edge removal)
46                    # Component 3: remaining part (total_xor ^ first_subtree_xor ^ second_subtree_xor)
47                    remaining_xor = total_xor ^ first_subtree_xor
48                    component1 = remaining_xor ^ second_subtree_xor
49                    component2 = second_subtree_xor
50                    component3 = first_subtree_xor
51                  
52                    # Find maximum and minimum among three components
53                    max_xor = max(component1, component2, component3)
54                    min_xor = min(component1, component2, component3)
55                  
56                    # Update minimum score
57                    min_score = min(min_score, max_xor - min_xor)
58          
59            return subtree_xor
60      
61        # Build adjacency list representation of the tree
62        graph = defaultdict(list)
63        for node_a, node_b in edges:
64            graph[node_a].append(node_b)
65            graph[node_b].append(node_a)
66      
67        # Calculate total XOR of all nodes
68        total_xor = reduce(lambda x, y: x ^ y, nums)
69      
70        n = len(nums)
71        min_score = float('inf')
72      
73        # Try each edge as the first edge to remove
74        for node in range(n):
75            for neighbor in graph[node]:
76                # Remove edge between 'node' and 'neighbor'
77                # Calculate XOR of subtree rooted at 'node' (with 'neighbor' as parent)
78                first_subtree_xor = calculate_subtree_xor(node, neighbor)
79              
80                # Find optimal second edge to remove
81                find_minimum_score(node, neighbor)
82      
83        return min_score
84
1class Solution {
2    private int[] nodeValues;
3    private List<Integer>[] adjacencyList;
4    private int minScore = Integer.MAX_VALUE;
5    private int totalXor;
6    private int firstSubtreeXor;
7
8    public int minimumScore(int[] nums, int[][] edges) {
9        int nodeCount = nums.length;
10        this.nodeValues = nums;
11      
12        // Build adjacency list representation of the tree
13        adjacencyList = new List[nodeCount];
14        Arrays.setAll(adjacencyList, index -> new ArrayList<>());
15        for (int[] edge : edges) {
16            int nodeA = edge[0];
17            int nodeB = edge[1];
18            adjacencyList[nodeA].add(nodeB);
19            adjacencyList[nodeB].add(nodeA);
20        }
21      
22        // Calculate total XOR of all node values
23        for (int value : nums) {
24            totalXor ^= value;
25        }
26      
27        // Try removing each edge as the first edge
28        for (int node = 0; node < nodeCount; ++node) {
29            for (int neighbor : adjacencyList[node]) {
30                // Calculate XOR of subtree rooted at neighbor when edge (node, neighbor) is removed
31                firstSubtreeXor = calculateSubtreeXor(node, neighbor);
32                // Try removing a second edge within the remaining tree
33                findSecondCut(node, neighbor);
34            }
35        }
36      
37        return minScore;
38    }
39
40    /**
41     * Calculate XOR of all values in subtree rooted at current node
42     * @param current Current node being processed
43     * @param parent Parent node to avoid revisiting
44     * @return XOR of all values in the subtree
45     */
46    private int calculateSubtreeXor(int current, int parent) {
47        int subtreeXor = nodeValues[current];
48      
49        for (int neighbor : adjacencyList[current]) {
50            if (neighbor != parent) {
51                subtreeXor ^= calculateSubtreeXor(neighbor, current);
52            }
53        }
54      
55        return subtreeXor;
56    }
57
58    /**
59     * Try removing a second edge and update minimum score
60     * @param current Current node being processed
61     * @param parent Parent node to avoid revisiting
62     * @return XOR of all values in the subtree rooted at current node
63     */
64    private int findSecondCut(int current, int parent) {
65        int subtreeXor = nodeValues[current];
66      
67        for (int neighbor : adjacencyList[current]) {
68            if (neighbor != parent) {
69                // Calculate XOR of second subtree when edge (current, neighbor) is removed
70                int secondSubtreeXor = findSecondCut(neighbor, current);
71                subtreeXor ^= secondSubtreeXor;
72              
73                // Calculate XOR values of the three components:
74                // 1. totalXor ^ firstSubtreeXor: remaining tree after removing first subtree
75                // 2. secondSubtreeXor: second subtree
76                // 3. firstSubtreeXor ^ secondSubtreeXor: first subtree minus second subtree
77                int component1 = totalXor ^ firstSubtreeXor;
78                int component2 = secondSubtreeXor;
79                int component3 = firstSubtreeXor ^ secondSubtreeXor;
80              
81                // Find maximum and minimum among the three components
82                int maxXor = Math.max(Math.max(component1, component2), component3);
83                int minXor = Math.min(Math.min(component1, component2), component3);
84              
85                // Update minimum score
86                minScore = Math.min(minScore, maxXor - minXor);
87            }
88        }
89      
90        return subtreeXor;
91    }
92}
93
1class Solution {
2public:
3    int minimumScore(vector<int>& nums, vector<vector<int>>& edges) {
4        int n = nums.size();
5      
6        // Build adjacency list for the tree
7        vector<vector<int>> adjacencyList(n);
8        for (const auto& edge : edges) {
9            int nodeA = edge[0];
10            int nodeB = edge[1];
11            adjacencyList[nodeA].push_back(nodeB);
12            adjacencyList[nodeB].push_back(nodeA);
13        }
14      
15        // Calculate total XOR of all node values
16        int totalXor = 0;
17        for (int value : nums) {
18            totalXor ^= value;
19        }
20      
21        int firstSubtreeXor = 0;
22        int minScore = INT_MAX;
23      
24        // DFS to calculate XOR sum of subtree rooted at current node
25        // excluding the parent edge
26        auto calculateSubtreeXor = [&](this auto&& calculateSubtreeXor, 
27                                       int currentNode, int parentNode) -> int {
28            int subtreeXor = nums[currentNode];
29          
30            // Traverse all children (neighbors except parent)
31            for (int childNode : adjacencyList[currentNode]) {
32                if (childNode != parentNode) {
33                    subtreeXor ^= calculateSubtreeXor(childNode, currentNode);
34                }
35            }
36          
37            return subtreeXor;
38        };
39      
40        // DFS to find the second edge to remove and calculate minimum score
41        // This explores all possible second edges after fixing the first edge
42        auto findSecondCutAndUpdateScore = [&](this auto&& findSecondCutAndUpdateScore, 
43                                               int currentNode, int parentNode) -> int {
44            int subtreeXor = nums[currentNode];
45          
46            // Traverse all children
47            for (int childNode : adjacencyList[currentNode]) {
48                if (childNode != parentNode) {
49                    // Calculate XOR of second subtree (rooted at childNode)
50                    int secondSubtreeXor = findSecondCutAndUpdateScore(childNode, currentNode);
51                    subtreeXor ^= secondSubtreeXor;
52                  
53                    // Three parts after removing two edges:
54                    // 1. totalXor ^ firstSubtreeXor: remaining tree after removing first subtree
55                    // 2. secondSubtreeXor: the second subtree we just calculated
56                    // 3. firstSubtreeXor ^ secondSubtreeXor: first subtree minus second subtree
57                    int part1 = totalXor ^ firstSubtreeXor;
58                    int part2 = secondSubtreeXor;
59                    int part3 = firstSubtreeXor ^ secondSubtreeXor;
60                  
61                    // Calculate score as difference between max and min XOR values
62                    int maxXor = max({part1, part2, part3});
63                    int minXor = min({part1, part2, part3});
64                    minScore = min(minScore, maxXor - minXor);
65                }
66            }
67          
68            return subtreeXor;
69        };
70      
71        // Try all possible first edges to remove
72        for (int nodeI = 0; nodeI < n; ++nodeI) {
73            for (int nodeJ : adjacencyList[nodeI]) {
74                // Remove edge (nodeI, nodeJ) as the first cut
75                // Calculate XOR of subtree rooted at nodeI (excluding edge to nodeJ)
76                firstSubtreeXor = calculateSubtreeXor(nodeI, nodeJ);
77              
78                // Find the best second edge to remove from the subtree rooted at nodeI
79                findSecondCutAndUpdateScore(nodeI, nodeJ);
80            }
81        }
82      
83        return minScore;
84    }
85};
86
1/**
2 * Finds the minimum score after removing two edges from a tree
3 * @param nums - Array of XOR values for each node
4 * @param edges - Array of edges representing the tree structure
5 * @returns The minimum possible score (difference between max and min XOR values of three subtrees)
6 */
7function minimumScore(nums: number[], edges: number[][]): number {
8    const nodeCount: number = nums.length;
9  
10    // Build adjacency list representation of the tree
11    const adjacencyList: number[][] = Array.from({ length: nodeCount }, () => []);
12    for (const [nodeA, nodeB] of edges) {
13        adjacencyList[nodeA].push(nodeB);
14        adjacencyList[nodeB].push(nodeA);
15    }
16  
17    // Calculate total XOR of all node values
18    const totalXor: number = nums.reduce((acc, val) => acc ^ val, 0);
19  
20    // Store XOR value of first subtree after removing first edge
21    let firstSubtreeXor: number = 0;
22  
23    // Track minimum score across all possible edge removals
24    let minScore: number = Number.MAX_SAFE_INTEGER;
25  
26    /**
27     * DFS to calculate XOR sum of subtree rooted at current node
28     * @param currentNode - Current node being processed
29     * @param parentNode - Parent node to avoid revisiting
30     * @returns XOR sum of the subtree
31     */
32    function dfs(currentNode: number, parentNode: number): number {
33        let subtreeXor: number = nums[currentNode];
34      
35        for (const neighbor of adjacencyList[currentNode]) {
36            if (neighbor !== parentNode) {
37                subtreeXor ^= dfs(neighbor, currentNode);
38            }
39        }
40      
41        return subtreeXor;
42    }
43  
44    /**
45     * DFS to find second edge removal and calculate minimum score
46     * @param currentNode - Current node being processed
47     * @param parentNode - Parent node to avoid revisiting
48     * @returns XOR sum of the subtree
49     */
50    function dfs2(currentNode: number, parentNode: number): number {
51        let subtreeXor: number = nums[currentNode];
52      
53        for (const neighbor of adjacencyList[currentNode]) {
54            if (neighbor !== parentNode) {
55                // Calculate XOR for second subtree created by removing this edge
56                const secondSubtreeXor: number = dfs2(neighbor, currentNode);
57                subtreeXor ^= secondSubtreeXor;
58              
59                // Calculate XOR values for all three components after removing two edges
60                const remainingXor: number = totalXor ^ firstSubtreeXor;
61                const thirdSubtreeXor: number = firstSubtreeXor ^ secondSubtreeXor;
62              
63                // Find max and min among the three XOR values
64                const maxXor: number = Math.max(remainingXor, secondSubtreeXor, thirdSubtreeXor);
65                const minXor: number = Math.min(remainingXor, secondSubtreeXor, thirdSubtreeXor);
66              
67                // Update minimum score
68                minScore = Math.min(minScore, maxXor - minXor);
69            }
70        }
71      
72        return subtreeXor;
73    }
74  
75    // Try all possible first edge removals
76    for (let node = 0; node < nodeCount; ++node) {
77        for (const neighbor of adjacencyList[node]) {
78            // Remove edge between node and neighbor as first edge
79            firstSubtreeXor = dfs(node, neighbor);
80          
81            // Find optimal second edge removal
82            dfs2(node, neighbor);
83        }
84    }
85  
86    return minScore;
87}
88

Time and Space Complexity

The time complexity is O(n²), where n is the number of nodes in the tree.

Time Complexity Analysis:

  • The outer loop iterates through all n nodes
  • For each node i, we iterate through its adjacent nodes (neighbors in g[i])
  • For each edge (i, j), we call dfs(i, j) and dfs2(i, j)
  • Both dfs and dfs2 traverse the entire tree once, taking O(n) time each
  • Since a tree with n nodes has exactly n-1 edges, and we process each edge from both directions, we perform 2(n-1) iterations of the inner loop across all outer loop iterations
  • Total time: O(n) × O(n) = O(n²)

The space complexity is O(n), where n is the number of nodes in the tree.

Space Complexity Analysis:

  • The graph adjacency list g stores all edges, requiring O(n) space for a tree
  • The recursion stack depth for both dfs and dfs2 can go up to O(n) in the worst case (when the tree is a linear chain)
  • Variables s, s1, s2, and ans use O(1) space
  • Total space: O(n)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Component XOR Calculation After Edge Removal

One of the most common mistakes is incorrectly calculating the XOR values of the three components after removing two edges. The code has a subtle bug in how it computes the three component XOR values.

The Issue: In the find_minimum_score function, after removing two edges, the three components are calculated as:

  • component1 = remaining_xor ^ second_subtree_xor
  • component2 = second_subtree_xor
  • component3 = first_subtree_xor

However, this is incorrect. When we remove the first edge (between some node and its neighbor), we split the tree into two parts with XOR values first_subtree_xor and total_xor ^ first_subtree_xor. When we then remove a second edge within the first_subtree_xor component, creating a subtree with XOR second_subtree_xor, the three final components should be:

  • Component containing the second removed subtree: second_subtree_xor
  • Remainder of the first component: first_subtree_xor ^ second_subtree_xor
  • The untouched component from the first split: total_xor ^ first_subtree_xor

The Fix:

# Correct calculation of three components
component1 = total_xor ^ first_subtree_xor  # Untouched component
component2 = second_subtree_xor              # Second removed subtree
component3 = first_subtree_xor ^ second_subtree_xor  # Remainder of first component

2. Not Exploring Both Directions for Edge Removal

Another pitfall is only exploring second edge removals in one of the two components created by the first edge removal. The current code only explores removing a second edge from the component containing node (with XOR value first_subtree_xor), but it should also explore removing edges from the other component.

The Fix: After removing edge (node, neighbor), explore second edge removals in both resulting components:

# Explore second edge removal in first component
first_subtree_xor = calculate_subtree_xor(node, neighbor)
find_minimum_score(node, neighbor)

# Also explore second edge removal in the other component
other_subtree_xor = calculate_subtree_xor(neighbor, node)
find_minimum_score(neighbor, node)

3. Variable Naming Confusion

The variable names in the original code can be confusing and lead to logical errors. Using generic names like component1, component2, component3 or the original s, s1, s2 makes it hard to track which component is which.

The Fix: Use more descriptive variable names:

def find_minimum_score_with_second_cut(root: int, parent: int) -> int:
    nonlocal total_xor, first_component_xor, min_score
  
    current_subtree_xor = nums[root]
    for child in graph[root]:
        if child != parent:
            second_cut_subtree_xor = find_minimum_score_with_second_cut(child, root)
            current_subtree_xor ^= second_cut_subtree_xor
          
            # Three components after two cuts:
            outside_first_cut = total_xor ^ first_component_xor
            second_cut_component = second_cut_subtree_xor
            first_cut_remainder = first_component_xor ^ second_cut_subtree_xor
          
            max_xor = max(outside_first_cut, second_cut_component, first_cut_remainder)
            min_xor = min(outside_first_cut, second_cut_component, first_cut_remainder)
            min_score = min(min_score, max_xor - min_xor)
  
    return current_subtree_xor

These improvements make the code more correct, complete, and maintainable.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

A person thinks of a number between 1 and 1000. You may ask any number questions to them, provided that the question can be answered with either "yes" or "no".

What is the minimum number of questions you needed to ask so that you are guaranteed to know the number that the person is thinking?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More