|
| 1 | +# [3004. Maximum Subtree of the Same Color](https://leetcode.cn/problems/maximum-subtree-of-the-same-color) |
| 2 | + |
| 3 | +[English Version](/solution/3000-3099/3004.Maximum%20Subtree%20of%20the%20Same%20Color/README_EN.md) |
| 4 | + |
| 5 | +## 题目描述 |
| 6 | + |
| 7 | +<!-- 这里写题目描述 --> |
| 8 | + |
| 9 | +<p>You are given a 2D integer array <code>edges</code> representing a tree with <code>n</code> nodes, numbered from <code>0</code> to <code>n - 1</code>, rooted at node <code>0</code>, where <code>edges[i] = [u<sub>i</sub>, v<sub>i</sub>]</code> means there is an edge between the nodes <code>v<sub>i</sub></code> and <code>u<sub>i</sub></code>.</p> |
| 10 | + |
| 11 | +<p>You are also given a <strong>0-indexed</strong> integer array <code>colors</code> of size <code>n</code>, where <code>colors[i]</code> is the color assigned to node <code>i</code>.</p> |
| 12 | + |
| 13 | +<p>We want to find a node <code>v</code> such that every node in the <span data-keyword="subtree-of-node">subtree</span> of <code>v</code> has the <strong>same</strong> color.</p> |
| 14 | + |
| 15 | +<p>Return <em>the size of such subtree with the <strong>maximum</strong> number of nodes possible.</em></p> |
| 16 | + |
| 17 | +<p> </p> |
| 18 | +<p><strong><img alt="" src="https://assets.leetcode.com/static_assets/others/20231216-134026.png" style="padding: 10px; background: rgb(255, 255, 255); border-radius: 0.5rem; width: 221px; height: 132px;" /></strong></p> |
| 19 | + |
| 20 | +<p><strong class="example">Example 1:</strong></p> |
| 21 | + |
| 22 | +<pre> |
| 23 | +<strong>Input:</strong> edges = [[0,1],[0,2],[0,3]], colors = [1,1,2,3] |
| 24 | +<strong>Output:</strong> 1 |
| 25 | +<strong>Explanation:</strong> Each color is represented as: 1 -> Red, 2 -> Green, 3 -> Blue. We can see that the subtree rooted at node 0 has children with different colors. Any other subtree is of the same color and has a size of 1. Hence, we return 1. |
| 26 | +</pre> |
| 27 | + |
| 28 | +<p><strong class="example">Example 2:</strong></p> |
| 29 | + |
| 30 | +<pre> |
| 31 | +<strong>Input:</strong> edges = [[0,1],[0,2],[0,3]], colors = [1,1,1,1] |
| 32 | +<strong>Output:</strong> 4 |
| 33 | +<strong>Explanation:</strong> The whole tree has the same color, and the subtree rooted at node 0 has the most number of nodes which is 4. Hence, we return 4. |
| 34 | +</pre> |
| 35 | + |
| 36 | +<p><strong><img alt="" src="https://assets.leetcode.com/static_assets/others/20231216-134017.png" style="padding: 10px; background: rgb(255, 255, 255); border-radius: 0.5rem; width: 221px; height: 221px;" /></strong></p> |
| 37 | + |
| 38 | +<p><strong class="example">Example 3:</strong></p> |
| 39 | + |
| 40 | +<pre> |
| 41 | +<strong>Input:</strong> edges = [[0,1],[0,2],[2,3],[2,4]], colors = [1,2,3,3,3] |
| 42 | +<strong>Output:</strong> 3 |
| 43 | +<strong>Explanation:</strong> Each color is represented as: 1 -> Red, 2 -> Green, 3 -> Blue. We can see that the subtree rooted at node 0 has children with different colors. Any other subtree is of the same color, but the subtree rooted at node 2 has a size of 3 which is the maximum. Hence, we return 3. |
| 44 | +</pre> |
| 45 | + |
| 46 | +<p> </p> |
| 47 | +<p><strong>Constraints:</strong></p> |
| 48 | + |
| 49 | +<ul> |
| 50 | + <li><code>n == edges.length + 1</code></li> |
| 51 | + <li><code>1 <= n <= 5 * 10<sup>4</sup></code></li> |
| 52 | + <li><code>edges[i] == [u<sub>i</sub>, v<sub>i</sub>]</code></li> |
| 53 | + <li><code>0 <= u<sub>i</sub>, v<sub>i</sub> < n</code></li> |
| 54 | + <li><code>colors.length == n</code></li> |
| 55 | + <li><code>1 <= colors[i] <= 10<sup>5</sup></code></li> |
| 56 | + <li>The input is generated such that the graph represented by <code>edges</code> is a tree.</li> |
| 57 | +</ul> |
| 58 | + |
| 59 | +## 解法 |
| 60 | + |
| 61 | +<!-- 这里可写通用的实现逻辑 --> |
| 62 | + |
| 63 | +**方法一:DFS** |
| 64 | + |
| 65 | +我们先根据题目给定的边的信息,构建一个邻接表 $g$,其中 $g[a]$ 表示节点 $a$ 的所有相邻节点。然后我们创建一个长度为 $n$ 的数组 $size$,其中 $size[a]$ 表示以节点 $a$ 为根的子树的节点数。 |
| 66 | + |
| 67 | +接下来,我们设计一个函数 $dfs(a, fa)$,它将返回以节点 $a$ 为根的子树是否满足题目要求。函数 $dfs(a, fa)$ 的执行过程如下: |
| 68 | + |
| 69 | +- 首先,我们用一个变量 $ok$ 记录以节点 $a$ 为根的子树是否满足题目要求,初始时 $ok$ 为 $true$。 |
| 70 | +- 接着,我们遍历节点 $a$ 的所有相邻节点 $b$,如果 $b$ 不是 $a$ 的父节点 $fa$,那么我们递归调用 $dfs(b, a)$,并将返回值保存到变量 $t$ 中,并且更新 $ok$ 为 $ok$ 与 $colors[a] = colors[b] \land t$ 的值,其中 $\land$ 表示逻辑与运算。然后,我们更新 $size[a] = size[a] + size[b]$。 |
| 71 | +- 然后,我们判断 $ok$ 的值,如果 $ok$ 为 $true$,那么我们更新答案 $ans = \max(ans, size[a])$。 |
| 72 | +- 最后,我们返回 $ok$ 的值。 |
| 73 | + |
| 74 | +我们调用 $dfs(0, -1)$,其中 $0$ 表示根节点的编号,$-1$ 表示根节点没有父节点。最终的答案即为 $ans$。 |
| 75 | + |
| 76 | +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是节点的数量。 |
| 77 | + |
| 78 | +<!-- tabs:start --> |
| 79 | + |
| 80 | +### **Python3** |
| 81 | + |
| 82 | +<!-- 这里可写当前语言的特殊实现逻辑 --> |
| 83 | + |
| 84 | +```python |
| 85 | +class Solution: |
| 86 | + def maximumSubtreeSize(self, edges: List[List[int]], colors: List[int]) -> int: |
| 87 | + def dfs(a: int, fa: int) -> bool: |
| 88 | + ok = True |
| 89 | + for b in g[a]: |
| 90 | + if b != fa: |
| 91 | + t = dfs(b, a) |
| 92 | + ok = ok and colors[a] == colors[b] and t |
| 93 | + size[a] += size[b] |
| 94 | + if ok: |
| 95 | + nonlocal ans |
| 96 | + ans = max(ans, size[a]) |
| 97 | + return ok |
| 98 | + |
| 99 | + n = len(edges) + 1 |
| 100 | + g = [[] for _ in range(n)] |
| 101 | + size = [1] * n |
| 102 | + for a, b in edges: |
| 103 | + g[a].append(b) |
| 104 | + g[b].append(a) |
| 105 | + ans = 0 |
| 106 | + dfs(0, -1) |
| 107 | + return ans |
| 108 | +``` |
| 109 | + |
| 110 | +### **Java** |
| 111 | + |
| 112 | +<!-- 这里可写当前语言的特殊实现逻辑 --> |
| 113 | + |
| 114 | +```java |
| 115 | +class Solution { |
| 116 | + private List<Integer>[] g; |
| 117 | + private int[] colors; |
| 118 | + private int[] size; |
| 119 | + private int ans; |
| 120 | + |
| 121 | + public int maximumSubtreeSize(int[][] edges, int[] colors) { |
| 122 | + int n = edges.length + 1; |
| 123 | + g = new List[n]; |
| 124 | + size = new int[n]; |
| 125 | + this.colors = colors; |
| 126 | + Arrays.fill(size, 1); |
| 127 | + Arrays.setAll(g, i -> new ArrayList<>()); |
| 128 | + for (var e : edges) { |
| 129 | + int a = e[0], b = e[1]; |
| 130 | + g[a].add(b); |
| 131 | + g[b].add(a); |
| 132 | + } |
| 133 | + dfs(0, -1); |
| 134 | + return ans; |
| 135 | + } |
| 136 | + |
| 137 | + private boolean dfs(int a, int fa) { |
| 138 | + boolean ok = true; |
| 139 | + for (int b : g[a]) { |
| 140 | + if (b != fa) { |
| 141 | + boolean t = dfs(b, a); |
| 142 | + ok = ok && colors[a] == colors[b] && t; |
| 143 | + size[a] += size[b]; |
| 144 | + } |
| 145 | + } |
| 146 | + if (ok) { |
| 147 | + ans = Math.max(ans, size[a]); |
| 148 | + } |
| 149 | + return ok; |
| 150 | + } |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +### **C++** |
| 155 | + |
| 156 | +```cpp |
| 157 | +class Solution { |
| 158 | +public: |
| 159 | + int maximumSubtreeSize(vector<vector<int>>& edges, vector<int>& colors) { |
| 160 | + int n = edges.size() + 1; |
| 161 | + vector<int> g[n]; |
| 162 | + vector<int> size(n, 1); |
| 163 | + for (auto& e : edges) { |
| 164 | + int a = e[0], b = e[1]; |
| 165 | + g[a].push_back(b); |
| 166 | + g[b].push_back(a); |
| 167 | + } |
| 168 | + int ans = 0; |
| 169 | + function<bool(int, int)> dfs = [&](int a, int fa) { |
| 170 | + bool ok = true; |
| 171 | + for (int b : g[a]) { |
| 172 | + if (b != fa) { |
| 173 | + bool t = dfs(b, a); |
| 174 | + ok = ok && colors[a] == colors[b] && t; |
| 175 | + size[a] += size[b]; |
| 176 | + } |
| 177 | + } |
| 178 | + if (ok) { |
| 179 | + ans = max(ans, size[a]); |
| 180 | + } |
| 181 | + return ok; |
| 182 | + }; |
| 183 | + dfs(0, -1); |
| 184 | + return ans; |
| 185 | + } |
| 186 | +}; |
| 187 | +``` |
| 188 | +
|
| 189 | +### **Go** |
| 190 | +
|
| 191 | +```go |
| 192 | +func maximumSubtreeSize(edges [][]int, colors []int) (ans int) { |
| 193 | + n := len(edges) + 1 |
| 194 | + g := make([][]int, n) |
| 195 | + for _, e := range edges { |
| 196 | + a, b := e[0], e[1] |
| 197 | + g[a] = append(g[a], b) |
| 198 | + g[b] = append(g[b], a) |
| 199 | + } |
| 200 | + size := make([]int, n) |
| 201 | + var dfs func(int, int) bool |
| 202 | + dfs = func(a, fa int) bool { |
| 203 | + size[a] = 1 |
| 204 | + ok := true |
| 205 | + for _, b := range g[a] { |
| 206 | + if b != fa { |
| 207 | + t := dfs(b, a) |
| 208 | + ok = ok && t && colors[a] == colors[b] |
| 209 | + size[a] += size[b] |
| 210 | + } |
| 211 | + } |
| 212 | + if ok { |
| 213 | + ans = max(ans, size[a]) |
| 214 | + } |
| 215 | + return ok |
| 216 | + } |
| 217 | + dfs(0, -1) |
| 218 | + return |
| 219 | +} |
| 220 | +``` |
| 221 | + |
| 222 | +### **TypeScript** |
| 223 | + |
| 224 | +```ts |
| 225 | +function maximumSubtreeSize(edges: number[][], colors: number[]): number { |
| 226 | + const n = edges.length + 1; |
| 227 | + const g: number[][] = Array.from({ length: n }, () => []); |
| 228 | + for (const [a, b] of edges) { |
| 229 | + g[a].push(b); |
| 230 | + g[b].push(a); |
| 231 | + } |
| 232 | + const size: number[] = Array(n).fill(1); |
| 233 | + let ans = 0; |
| 234 | + const dfs = (a: number, fa: number): boolean => { |
| 235 | + let ok = true; |
| 236 | + for (const b of g[a]) { |
| 237 | + if (b !== fa) { |
| 238 | + const t = dfs(b, a); |
| 239 | + ok = ok && t && colors[a] === colors[b]; |
| 240 | + size[a] += size[b]; |
| 241 | + } |
| 242 | + } |
| 243 | + if (ok) { |
| 244 | + ans = Math.max(ans, size[a]); |
| 245 | + } |
| 246 | + return ok; |
| 247 | + }; |
| 248 | + dfs(0, -1); |
| 249 | + return ans; |
| 250 | +} |
| 251 | +``` |
| 252 | + |
| 253 | +### **...** |
| 254 | + |
| 255 | +``` |
| 256 | +
|
| 257 | +``` |
| 258 | + |
| 259 | +<!-- tabs:end --> |
0 commit comments