|
| 1 | +/* |
| 2 | +
|
| 3 | +
|
| 4 | +*- 1519. Number of Nodes in the Sub-Tree With the Same Label *- |
| 5 | +
|
| 6 | +
|
| 7 | +You are given a tree (i.e. a connected, undirected graph that has no cycles) consisting of n nodes numbered from 0 to n - 1 and exactly n - 1 edges. The root of the tree is the node 0, and each node of the tree has a label which is a lower-case character given in the string labels (i.e. The node with the number i has the label labels[i]). |
| 8 | +
|
| 9 | +The edges array is given on the form edges[i] = [ai, bi], which means there is an edge between nodes ai and bi in the tree. |
| 10 | +
|
| 11 | +Return an array of size n where ans[i] is the number of nodes in the subtree of the ith node which have the same label as node i. |
| 12 | +
|
| 13 | +A subtree of a tree T is the tree consisting of a node in T and all of its descendant nodes. |
| 14 | +
|
| 15 | + |
| 16 | +
|
| 17 | +Example 1: |
| 18 | +
|
| 19 | +
|
| 20 | +Input: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = "abaedcd" |
| 21 | +Output: [2,1,1,1,1,1,1] |
| 22 | +Explanation: Node 0 has label 'a' and its sub-tree has node 2 with label 'a' as well, thus the answer is 2. Notice that any node is part of its sub-tree. |
| 23 | +Node 1 has a label 'b'. The sub-tree of node 1 contains nodes 1,4 and 5, as nodes 4 and 5 have different labels than node 1, the answer is just 1 (the node itself). |
| 24 | +Example 2: |
| 25 | +
|
| 26 | +
|
| 27 | +Input: n = 4, edges = [[0,1],[1,2],[0,3]], labels = "bbbb" |
| 28 | +Output: [4,2,1,1] |
| 29 | +Explanation: The sub-tree of node 2 contains only node 2, so the answer is 1. |
| 30 | +The sub-tree of node 3 contains only node 3, so the answer is 1. |
| 31 | +The sub-tree of node 1 contains nodes 1 and 2, both have label 'b', thus the answer is 2. |
| 32 | +The sub-tree of node 0 contains nodes 0, 1, 2 and 3, all with label 'b', thus the answer is 4. |
| 33 | +Example 3: |
| 34 | +
|
| 35 | +
|
| 36 | +Input: n = 5, edges = [[0,1],[0,2],[1,3],[0,4]], labels = "aabab" |
| 37 | +Output: [3,2,1,1,1] |
| 38 | + |
| 39 | +
|
| 40 | +Constraints: |
| 41 | +
|
| 42 | +1 <= n <= 105 |
| 43 | +edges.length == n - 1 |
| 44 | +edges[i].length == 2 |
| 45 | +0 <= ai, bi < n |
| 46 | +ai != bi |
| 47 | +labels.length == n |
| 48 | +labels is consisting of only of lowercase English letters. |
| 49 | +
|
| 50 | +
|
| 51 | +
|
| 52 | +*/ |
| 53 | + |
| 54 | +/* |
| 55 | +
|
| 56 | +We need to return the number of nodes in the subtree of the currentent node which have the same label as currentent node . To do that we use a HashMap of labels that are present in the subtree of the currentent node. |
| 57 | +So we use a function helper to do the same. |
| 58 | +
|
| 59 | +node -> an integer representing the currentent node being visited |
| 60 | +labels -> a character array representing the labels of the nodes in the tree. |
| 61 | +answer-> an integer array where answer[i] will store the number of subtrees with the same label as the i-th node. |
| 62 | +visited ->a boolean array where visited[i] will be used to keep track of whether the i-th node has been visited during the traversal. |
| 63 | +This function will return a HashMap with all the labels along with their counts of that subtree. |
| 64 | +The required output is stored in the array answer. |
| 65 | +
|
| 66 | +*/ |
| 67 | + |
| 68 | +import 'dart:collection'; |
| 69 | + |
| 70 | +class A { |
| 71 | + // Memory Limit Exceed |
| 72 | + late List<List<int>> canVisit; |
| 73 | + List<int> countSubTrees(int n, List<List<int>> edges, String labels) { |
| 74 | + canVisit = List.filled(n, 0).map((e) => List.filled(n, 0)).toList(); |
| 75 | + for (int i = 0; i < n; i++) canVisit[i] = []; |
| 76 | + for (List<int> edge in edges) { |
| 77 | + canVisit[edge[0]].add(edge[1]); |
| 78 | + canVisit[edge[1]].add(edge[0]); |
| 79 | + } |
| 80 | + List<bool> visited = List.filled(n, false); |
| 81 | + List<int> answer = List.filled(n, 0); |
| 82 | + helper(0, labels.split(""), answer, visited); |
| 83 | + return answer; |
| 84 | + } |
| 85 | + |
| 86 | + HashMap<String, int> helper( |
| 87 | + int node, List<String> labels, List<int> answer, List<bool> visited) { |
| 88 | + HashMap<String, int> currententHashMap = HashMap(); |
| 89 | + visited[node] = true; |
| 90 | + for (int i in canVisit[node]) { |
| 91 | + if (visited[i]) continue; |
| 92 | + HashMap<String, int> map = helper(i, labels, answer, visited); |
| 93 | + for (MapEntry<String, int> entry in map.entries) { |
| 94 | + currententHashMap[entry.key] = |
| 95 | + (currententHashMap[entry.key] ?? 0) + entry.value; |
| 96 | + } |
| 97 | + } |
| 98 | + currententHashMap[labels[node]] = |
| 99 | + (currententHashMap[labels[node]] ?? 0) + 1; |
| 100 | + answer[node] = currententHashMap[labels[node]]!; |
| 101 | + return currententHashMap; |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +class B { |
| 106 | + // Memory Limit Exceed |
| 107 | + late List<int> result; |
| 108 | + late List<List<int>> adj; |
| 109 | + late List<bool> visited; |
| 110 | + List<int> countSubTrees(int n, List<List<int>> edges, String labels) { |
| 111 | + //Creating an adjacency list to store the edges |
| 112 | + adj = List.filled(n, 0, growable: true) |
| 113 | + .map((e) => List.filled(n, 0, growable: true)) |
| 114 | + .toList(); |
| 115 | + result = List.filled(n, 0); |
| 116 | + //initializing the adjacency list |
| 117 | + for (int i = 0; i < n; i++) { |
| 118 | + adj.add([]); |
| 119 | + } |
| 120 | + //populating the adjacency list with the edges |
| 121 | + for (List<int> edge in edges) { |
| 122 | + adj[edge[0]].add(edge[1]); |
| 123 | + adj[edge[1]].add(edge[0]); |
| 124 | + } |
| 125 | + //keep track of visited nodes |
| 126 | + visited = List.filled(n, false); |
| 127 | + //calling the dfs function to count the subtrees starting from the root node |
| 128 | + dfs(0, labels); |
| 129 | + return result; |
| 130 | + } |
| 131 | + |
| 132 | + List<int> dfs(int node, String labels) { |
| 133 | + visited[node] = true; |
| 134 | + List<int> count = List.filled(26, 0); |
| 135 | + //visiting all the neighbors of the currentent node |
| 136 | + for (int nbr in adj[node]) { |
| 137 | + if (!visited[nbr]) { |
| 138 | + List<int> adjCount = dfs(nbr, labels); |
| 139 | + //updating the count array with the count of the subtrees of the neighbors |
| 140 | + for (int i = 0; i < 26; i++) { |
| 141 | + count[i] += adjCount[i]; |
| 142 | + } |
| 143 | + } |
| 144 | + } |
| 145 | + //incrementing the count of the currentent node label |
| 146 | + int ch = labels.codeUnitAt(node); |
| 147 | + count[ch - 'a'.codeUnitAt(0)]++; |
| 148 | + //storing the count of the subtrees of the currentent node |
| 149 | + result[node] = count[ch - 'a'.codeUnitAt(0)]; |
| 150 | + return count; |
| 151 | + } |
| 152 | +} |
| 153 | + |
| 154 | +class C { |
| 155 | + List<int> countSubTrees(int n, List<List<int>> edges, String labels) { |
| 156 | + List<List<int>> graph = List.filled(n, 0, growable: true) |
| 157 | + .map((e) => List.filled(n, 0, growable: true)) |
| 158 | + .toList(); |
| 159 | + int i; |
| 160 | + for (i = 0; i < n; i++) graph[i] = []; |
| 161 | + for (i = 0; i < edges.length; i++) { |
| 162 | + graph[edges[i][0]].add(edges[i][1]); |
| 163 | + graph[edges[i][1]].add(edges[i][0]); |
| 164 | + } |
| 165 | + List<int> ans = List.filled(n, 0); |
| 166 | + List<int> freq = List.filled(26, 0); |
| 167 | + List<bool> dp = List.filled(n, false); |
| 168 | + dfs(0, ans, freq, dp, labels, graph); |
| 169 | + return ans; |
| 170 | + } |
| 171 | + |
| 172 | + void dfs(int i, List<int> ans, List<int> freq, List<bool> dp, String s, |
| 173 | + List<List<int>> graph) { |
| 174 | + if (dp[i]) return; |
| 175 | + dp[i] = true; |
| 176 | + int c = s.codeUnitAt(i) - 'a'.codeUnitAt(0); |
| 177 | + int tmp = freq[c]; |
| 178 | + freq[c] = 1; |
| 179 | + for (int it in graph[i]) dfs(it, ans, freq, dp, s, graph); |
| 180 | + ans[i] = freq[c]; |
| 181 | + freq[c] += tmp; |
| 182 | + } |
| 183 | +} |
| 184 | + |
| 185 | +//================ |
| 186 | + |
| 187 | +class Node { |
| 188 | + late String c; |
| 189 | + late int key; |
| 190 | + late List<Node> cs; |
| 191 | + late Node? p; |
| 192 | + Node(int key) { |
| 193 | + this.key = key; |
| 194 | + cs = <Node>[]; |
| 195 | + this.p = null; |
| 196 | + } |
| 197 | +} |
| 198 | + |
| 199 | +class D { |
| 200 | + late List<int> res; |
| 201 | + Node build(int n, List<List<int>> es, String l) { |
| 202 | + HashMap<int, List<int>> g = HashMap(); |
| 203 | + for (List<int> e in es) { |
| 204 | + g.putIfAbsent(e[0], () => []); |
| 205 | + g.putIfAbsent(e[1], () => []); |
| 206 | + g[e[1]]?.add(e[0]); |
| 207 | + g[e[0]]?.add(e[1]); |
| 208 | + } |
| 209 | + Node root = Node(0); |
| 210 | + root.c = l[0]; |
| 211 | + Queue<Node> q = Queue(); |
| 212 | + q.add(root); |
| 213 | + while (!q.isEmpty) { |
| 214 | + Node current = q.removeLast(); |
| 215 | + for (int neighbor in g[current.key] ?? []) { |
| 216 | + if (current.p == null || neighbor != current.p?.key) { |
| 217 | + Node next = Node(neighbor); |
| 218 | + next.c = l[neighbor]; |
| 219 | + next.p = current; |
| 220 | + current.cs.add(next); |
| 221 | + q.add(next); |
| 222 | + } |
| 223 | + } |
| 224 | + } |
| 225 | + return root; |
| 226 | + } |
| 227 | + |
| 228 | + HashMap<String, int> dfs(Node? node) { |
| 229 | + HashMap<String, int> map = HashMap(); |
| 230 | + if (node == null) return map; |
| 231 | + map[node.c] = 1; |
| 232 | + for (Node child in node.cs) { |
| 233 | + HashMap<String, int> cHashMap = dfs(child); |
| 234 | + for (String c in cHashMap.keys) { |
| 235 | + map[c] = (map[c] ?? 0) + cHashMap[c]!; |
| 236 | + } |
| 237 | + } |
| 238 | + res[node.key] = map[node.c]!; |
| 239 | + return map; |
| 240 | + } |
| 241 | + |
| 242 | + List<int> countSubTrees(int n, List<List<int>> edges, String labels) { |
| 243 | + Node root = build(n, edges, labels); |
| 244 | + res = List.filled(n, 0, growable: true); |
| 245 | + dfs(root); |
| 246 | + return res; |
| 247 | + } |
| 248 | +} |
| 249 | + |
| 250 | +class E { |
| 251 | + // Time limit exceed |
| 252 | + late List<int> result; |
| 253 | + late HashSet<int> visited; |
| 254 | + late HashMap<int, HashSet<int>> graph; |
| 255 | + late String labels; |
| 256 | + List<int> countSubTrees(int n, List<List<int>> edges, String labels) { |
| 257 | + visited = HashSet(); |
| 258 | + this.labels = labels; |
| 259 | + result = List.filled(n, 0); |
| 260 | + graph = buildGraph(edges); |
| 261 | + findLabels(0); |
| 262 | + return result; |
| 263 | + } |
| 264 | + |
| 265 | + HashMap<int, HashSet<int>> buildGraph(List<List<int>> edges) { |
| 266 | + HashMap<int, HashSet<int>> map = HashMap(); |
| 267 | + for (List<int> e in edges) { |
| 268 | + int a = e[0]; |
| 269 | + int b = e[1]; |
| 270 | + addEdge(map, a, b); |
| 271 | + addEdge(map, b, a); |
| 272 | + } |
| 273 | + return map; |
| 274 | + } |
| 275 | + |
| 276 | + void addEdge(HashMap<int, HashSet<int>> HashMap, int a, int b) { |
| 277 | + if (!HashMap.containsKey(a)) { |
| 278 | + HashMap[a] = HashSet(); |
| 279 | + } |
| 280 | + HashMap[a]?.add(b); |
| 281 | + } |
| 282 | + |
| 283 | + List<int> findLabels(int root) { |
| 284 | + List<int> allLabelsCounter = List.filled(26, 0); |
| 285 | + if (visited.contains(root)) { |
| 286 | + return allLabelsCounter; |
| 287 | + } |
| 288 | + visited.add(root); |
| 289 | + HashSet<int> neighbors = graph[root]!; |
| 290 | + int labelIndex = labels.codeUnitAt(root) - 'a'.codeUnitAt(0); |
| 291 | + allLabelsCounter[labelIndex]++; |
| 292 | + if (neighbors.isEmpty || neighbors.length == 0) { |
| 293 | + result[root] = allLabelsCounter[labelIndex]; |
| 294 | + return allLabelsCounter; |
| 295 | + } |
| 296 | + for (int nbr in neighbors) { |
| 297 | + List<int> temp = findLabels(nbr); |
| 298 | + for (int i = 0; i < temp.length; i++) { |
| 299 | + allLabelsCounter[i] += temp[i]; |
| 300 | + } |
| 301 | + } |
| 302 | + result[root] = allLabelsCounter[labelIndex]; |
| 303 | + return allLabelsCounter; |
| 304 | + } |
| 305 | +} |
| 306 | + |
| 307 | +class TreeNode { |
| 308 | + late String val; |
| 309 | + late int index; |
| 310 | + late List<TreeNode> child; |
| 311 | + TreeNode(String val, int index) { |
| 312 | + this.val = val; |
| 313 | + this.index = index; |
| 314 | + child = []; |
| 315 | + } |
| 316 | +} |
| 317 | + |
| 318 | +class F { |
| 319 | + late List<int> res; |
| 320 | + late List<bool> visited; |
| 321 | + List<int> countSubTrees(int n, List<List<int>> edges, String labels) { |
| 322 | + List<TreeNode> nodes = List.filled(n, TreeNode(labels, 0)); |
| 323 | + // nodes.add(n); |
| 324 | + for (int i = 0; i < n; ++i) nodes[i] = new TreeNode(labels[i], i); |
| 325 | + for (int i = 0; i < n - 1; ++i) { |
| 326 | + int a = edges[i][0], b = edges[i][1]; |
| 327 | + nodes[a].child.add(nodes[b]); |
| 328 | + nodes[b].child.add(nodes[a]); |
| 329 | + } |
| 330 | + TreeNode root = nodes[0]; |
| 331 | + res = List.filled(n, 0); |
| 332 | + visited = List.filled(n, false); |
| 333 | + List.filled(res.length, 1); |
| 334 | + dfs(root); |
| 335 | + return res; |
| 336 | + } |
| 337 | + |
| 338 | + Map<String, int> dfs(TreeNode root) { |
| 339 | + HashMap<String, int> map = HashMap(); |
| 340 | + if (root == null) return map; |
| 341 | + visited[root.index] = true; |
| 342 | + map[root.val] = (map[root.val] ?? 0) + 1; |
| 343 | + for (TreeNode child in root.child) { |
| 344 | + if (visited[child.index]) continue; |
| 345 | + Map<String, int> temp = dfs(child); |
| 346 | + if (temp.containsKey(root.val)) res[root.index] += temp[root.val]!; |
| 347 | + for (String key in temp.keys) { |
| 348 | + map[key] = (map[key] ?? 0) + temp[key]!; |
| 349 | + } |
| 350 | + } |
| 351 | + return map; |
| 352 | + } |
| 353 | +} |
0 commit comments