Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 457c4b4

Browse files
committed
Add solution and test-cases for problem 2322
1 parent 8ae5d85 commit 457c4b4

File tree

5 files changed

+166
-26
lines changed

5 files changed

+166
-26
lines changed
20 KB
Loading[フレーム]
16.5 KB
Loading[フレーム]

‎leetcode/2301-2400/2322.Minimum-Score-After-Removals-on-a-Tree/README.md‎

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,48 @@
11
# [2322.Minimum Score After Removals on a Tree][title]
22

3-
> [!WARNING|style:flat]
4-
> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm)
5-
63
## Description
4+
There is an undirected connected tree with n nodes labeled from `0` to `n - 1` and `n - 1` edges.
5+
6+
You are given a **0-indexed** integer array `nums` of length `n` where `nums[i]` represents the value of the `ith` node. You are also given a 2D integer array `edges` of length `n - 1` where `edges[i] = [ai, bi]` indicates that there is an edge between nodes `ai` and `bi` in the tree.
7+
8+
Remove two **distinct** edges of the tree to form three connected components. For a pair of removed edges, the following steps are defined:
9+
10+
1. Get the XOR of all the values of the nodes for **each** of the three components respectively.
11+
2. The **difference** between the **largest** XOR value and the **smallest** XOR value is the **score** of the pair.
12+
13+
- For example, say the three components have the node values: `[4,5,7], [1,9], and [3,3,3]`. The three XOR values are `4 ^ 5 ^ 7 = 6`, `1 ^ 9 = 8`, and `3 ^ 3 ^ 3 = 3`. The largest XOR value is `8` and the smallest XOR value is `3`. The score is then `8 - 3 = 5`.
714

8-
**Example 1:**
15+
Return the **minimum** score of any possible pair of edge removals on the given tree.
16+
17+
**Example 1:**
18+
19+
![1](./1.png)
920

1021
```
11-
Input: a = "11", b = "1"
12-
Output: "100"
22+
Input: nums = [1,5,5,4,11], edges = [[0,1],[1,2],[1,3],[3,4]]
23+
Output: 9
24+
Explanation: The diagram above shows a way to make a pair of removals.
25+
- The 1st component has nodes [1,3,4] with values [5,4,11]. Its XOR value is 5 ^ 4 ^ 11 = 10.
26+
- The 2nd component has node [0] with value [1]. Its XOR value is 1 = 1.
27+
- The 3rd component has node [2] with value [5]. Its XOR value is 5 = 5.
28+
The score is the difference between the largest and smallest XOR value which is 10 - 1 = 9.
29+
It can be shown that no other pair of removals will obtain a smaller score than 9.
1330
```
1431

15-
## 题意
16-
> ...
32+
**Example 2:**
1733

18-
## 题解
34+
![2](./2.png)
1935

20-
### 思路1
21-
> ...
22-
Minimum Score After Removals on a Tree
23-
```go
2436
```
25-
37+
Input: nums = [5,5,2,4,4,2], edges = [[0,1],[1,2],[5,2],[4,3],[1,3]]
38+
Output: 0
39+
Explanation: The diagram above shows a way to make a pair of removals.
40+
- The 1st component has nodes [3,4] with values [4,4]. Its XOR value is 4 ^ 4 = 0.
41+
- The 2nd component has nodes [1,0] with values [5,5]. Its XOR value is 5 ^ 5 = 0.
42+
- The 3rd component has nodes [2,5] with values [2,2]. Its XOR value is 2 ^ 2 = 0.
43+
The score is the difference between the largest and smallest XOR value which is 0 - 0 = 0.
44+
We cannot obtain a smaller score than 0.
45+
```
2646

2747
## 结语
2848

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,121 @@
11
package Solution
22

3-
func Solution(x bool) bool {
4-
return x
3+
import (
4+
"math"
5+
"sort"
6+
)
7+
8+
// minimumScore calculates the minimum score achievable by removing two distinct edges from a tree.
9+
// The score is defined as the difference between the largest and smallest XOR values of the three resulting components.
10+
func Solution(nums []int, edges [][]int) int {
11+
n := len(nums) // Number of nodes
12+
13+
// 1. Build adjacency list for graph traversal
14+
adj := make([][]int, n)
15+
for _, edge := range edges {
16+
u, v := edge[0], edge[1]
17+
adj[u] = append(adj[u], v)
18+
adj[v] = append(adj[v], u) // Undirected graph
19+
}
20+
21+
// 2. Calculate the total XOR sum of all node values
22+
totalXorSum := 0
23+
for _, num := range nums {
24+
totalXorSum ^= num
25+
}
26+
27+
// 3. Prepare slices for DFS pre-calculation
28+
// subtreeXor[i]: XOR sum of nodes in the subtree rooted at i (including i)
29+
subtreeXor := make([]int, n)
30+
// tin[i]: Entry time of node i in DFS traversal
31+
tin := make([]int, n)
32+
// tout[i]: Exit time of node i in DFS traversal (after visiting all its descendants)
33+
tout := make([]int, n)
34+
timer := 0 // Global timer for assigning tin/tout values
35+
36+
// DFS function to compute subtreeXor, tin, and tout
37+
var dfs func(u, p int) // u: current node, p: parent node
38+
dfs = func(u, p int) {
39+
timer++
40+
tin[u] = timer // Mark entry time for node u
41+
42+
subtreeXor[u] = nums[u] // Initialize subtree XOR with current node's value
43+
44+
// Traverse all neighbors of u
45+
for _, v := range adj[u] {
46+
if v == p { // Skip if v is the parent of u
47+
continue
48+
}
49+
dfs(v, u) // Recursively call DFS for child v
50+
subtreeXor[u] ^= subtreeXor[v] // Aggregate child's subtree XOR into current node's
51+
}
52+
53+
timer++
54+
tout[u] = timer // Mark exit time for node u
55+
}
56+
57+
// Start DFS from node 0 (arbitrary root), with -1 as its virtual parent
58+
dfs(0, -1)
59+
60+
// Initialize minimum score to a very large value
61+
minScore := math.MaxInt32
62+
63+
// 4. Enumerate all possible pairs of distinct nodes (i, j)
64+
// These nodes represent the "roots" of the two subtrees that will be cut off.
65+
// The edges being cut are implicitly (parent[i], i) and (parent[j], j).
66+
// We start from node 1 because node 0 is the root and does not have a "parent edge" to cut.
67+
for i := 1; i < n; i++ {
68+
for j := i + 1; j < n; j++ { // j must be different from i
69+
70+
// Check if i is an ancestor of j using DFS timestamps
71+
// (tin[i] < tin[j] and tout[i] > tout[j])
72+
isIAncestorOfJ := (tin[i] < tin[j] && tout[i] > tout[j])
73+
// Check if j is an ancestor of i using DFS timestamps
74+
isJAncestorOfI := (tin[j] < tin[i] && tout[j] > tout[i])
75+
76+
var xorVal1, xorVal2, xorVal3 int // The three component XOR sums
77+
78+
if isIAncestorOfJ {
79+
// Case 1: Node i is an ancestor of node j.
80+
// This means j's subtree is entirely contained within i's subtree.
81+
// The three components are:
82+
// - Component A: The subtree rooted at j. (xorVal1)
83+
// - Component B: The part of i's subtree *outside* j's subtree. (xorVal2)
84+
// - Component C: The rest of the tree (outside i's subtree). (xorVal3)
85+
xorVal1 = subtreeXor[j]
86+
xorVal2 = subtreeXor[i] ^ subtreeXor[j] // XOR sum of i's subtree excluding j's subtree
87+
xorVal3 = totalXorSum ^ subtreeXor[i] // Total XOR sum excluding i's subtree
88+
} else if isJAncestorOfI {
89+
// Case 2: Node j is an ancestor of node i.
90+
// This is symmetric to Case 1. Swap roles of i and j for calculation.
91+
xorVal1 = subtreeXor[i]
92+
xorVal2 = subtreeXor[j] ^ subtreeXor[i] // XOR sum of j's subtree excluding i's subtree
93+
xorVal3 = totalXorSum ^ subtreeXor[j] // Total XOR sum excluding j's subtree
94+
} else {
95+
// Case 3: Nodes i and j are not ancestors of each other.
96+
// Their respective subtrees are disjoint.
97+
// The three components are:
98+
// - Component A: The subtree rooted at i. (xorVal1)
99+
// - Component B: The subtree rooted at j. (xorVal2)
100+
// - Component C: The rest of the tree (outside both i's and j's subtrees). (xorVal3)
101+
xorVal1 = subtreeXor[i]
102+
xorVal2 = subtreeXor[j]
103+
xorVal3 = totalXorSum ^ subtreeXor[i] ^ subtreeXor[j] // Total XOR sum excluding both i's and j's subtrees
104+
}
105+
106+
// Store the three XOR values in a slice, sort them, and calculate the difference.
107+
currentXors := []int{xorVal1, xorVal2, xorVal3}
108+
sort.Ints(currentXors) // Sort to easily find min and max
109+
110+
// Calculate the score for this pair of edge removals
111+
diff := currentXors[2] - currentXors[0] // Largest XOR - Smallest XOR
112+
113+
// Update the minimum score found so far
114+
if diff < minScore {
115+
minScore = diff
116+
}
117+
}
118+
}
119+
120+
return minScore
5121
}

‎leetcode/2301-2400/2322.Minimum-Score-After-Removals-on-a-Tree/Solution_test.go‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,34 @@ func TestSolution(t *testing.T) {
1010
// 测试用例
1111
cases := []struct {
1212
name string
13-
inputs bool
14-
expect bool
13+
nums []int
14+
edges [][]int
15+
expect int
1516
}{
16-
{"TestCase", true, true},
17-
{"TestCase", true, true},
18-
{"TestCase", false, false},
17+
{"TestCase1", []int{1, 5, 5, 4, 11}, [][]int{
18+
{0, 1}, {1, 2}, {1, 3}, {3, 4},
19+
}, 9},
20+
{"TestCase2", []int{5, 5, 2, 4, 4, 2}, [][]int{
21+
{0, 1}, {1, 2}, {5, 2}, {4, 3}, {1, 3},
22+
}, 0},
1923
}
2024

2125
// 开始测试
2226
for i, c := range cases {
2327
t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) {
24-
got := Solution(c.inputs)
28+
got := Solution(c.nums, c.edges)
2529
if !reflect.DeepEqual(got, c.expect) {
26-
t.Fatalf("expected: %v, but got: %v, with inputs: %v",
27-
c.expect, got, c.inputs)
30+
t.Fatalf("expected: %v, but got: %v, with inputs: %v %v",
31+
c.expect, got, c.nums, c.edges)
2832
}
2933
})
3034
}
3135
}
3236

33-
//压力测试
37+
//压力测试
3438
func BenchmarkSolution(b *testing.B) {
3539
}
3640

37-
//使用案列
41+
//使用案列
3842
func ExampleSolution() {
3943
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /