{"id":7119,"date":"2020-07-18T22:14:52","date_gmt":"2020-07-19T05:14:52","guid":{"rendered":"https:\/\/zxi.mytechroad.com\/blog\/?p=7119"},"modified":"2020-07-18T23:45:12","modified_gmt":"2020-07-19T06:45:12","slug":"leetcode-1519-number-of-nodes-in-the-sub-tree-with-the-same-label","status":"publish","type":"post","link":"https:\/\/zxi.mytechroad.com\/blog\/tree\/leetcode-1519-number-of-nodes-in-the-sub-tree-with-the-same-label\/","title":{"rendered":"\u82b1\u82b1\u9171 LeetCode 1519. Number of Nodes in the Sub-Tree With the Same Label"},"content":{"rendered":"\n<p>Given a tree (i.e. a connected, undirected graph that has no cycles) consisting of&nbsp;<code>n<\/code>&nbsp;nodes numbered from&nbsp;<code>0<\/code>&nbsp;to&nbsp;<code>n - 1<\/code>&nbsp;and exactly&nbsp;<code>n - 1<\/code>&nbsp;<code>edges<\/code>. The&nbsp;<strong>root<\/strong>&nbsp;of the tree is the node&nbsp;<code>0<\/code>, and each node of the tree has&nbsp;<strong>a label<\/strong>&nbsp;which is a lower-case character given in the string&nbsp;<code>labels<\/code>&nbsp;(i.e. The node with the number&nbsp;<code>i<\/code>&nbsp;has the label&nbsp;<code>labels[i]<\/code>).<\/p>\n\n\n\n<p>The&nbsp;<code>edges<\/code>&nbsp;array is given on the form&nbsp;<code>edges[i] = [a<sub>i<\/sub>, b<sub>i<\/sub>]<\/code>, which means there is an edge between nodes&nbsp;<code>a<sub>i<\/sub><\/code>&nbsp;and&nbsp;<code>b<sub>i<\/sub><\/code>&nbsp;in the tree.<\/p>\n\n\n\n<p>Return&nbsp;<em>an array of size&nbsp;<code>n<\/code><\/em>&nbsp;where&nbsp;<code>ans[i]<\/code>&nbsp;is the number of nodes in the subtree of the&nbsp;<code>i<sup>th<\/sup><\/code>&nbsp;node which have the same label as node&nbsp;<code>i<\/code>.<\/p>\n\n\n\n<p>A&nbsp;subtree&nbsp;of a tree&nbsp;<code>T<\/code>&nbsp;is the tree consisting of a node in&nbsp;<code>T<\/code>&nbsp;and all of its descendant&nbsp;nodes.<\/p>\n\n\n\n<p><strong>Example 1:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2020\/07\/01\/q3e1.jpg\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = \"abaedcd\"\n<strong>Output:<\/strong> [2,1,1,1,1,1,1]\n<strong>Explanation:<\/strong> 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.\nNode 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).\n<\/pre>\n\n\n\n<p><strong>Example 2:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2020\/07\/01\/q3e2.jpg\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> n = 4, edges = [[0,1],[1,2],[0,3]], labels = \"bbbb\"\n<strong>Output:<\/strong> [4,2,1,1]\n<strong>Explanation:<\/strong> The sub-tree of node 2 contains only node 2, so the answer is 1.\nThe sub-tree of node 3 contains only node 3, so the answer is 1.\nThe sub-tree of node 1 contains nodes 1 and 2, both have label 'b', thus the answer is 2.\nThe sub-tree of node 0 contains nodes 0, 1, 2 and 3, all with label 'b', thus the answer is 4.\n<\/pre>\n\n\n\n<p><strong>Example 3:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/assets.leetcode.com\/uploads\/2020\/07\/01\/q3e3.jpg\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> n = 5, edges = [[0,1],[0,2],[1,3],[0,4]], labels = \"aabab\"\n<strong>Output:<\/strong> [3,2,1,1,1]\n<\/pre>\n\n\n\n<p><strong>Example 4:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>Input:<\/strong> n = 6, edges = [[0,1],[0,2],[1,3],[3,4],[4,5]], labels = \"cbabaa\"\n<strong>Output:<\/strong> [1,2,1,1,2,1]\n<\/pre>\n\n\n\n<p><strong>Example 5:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input:<\/strong> n = 7, edges = [[0,1],[1,2],[2,3],[3,4],[4,5],[5,6]], labels = \"aaabaaa\"\n<strong>Output:<\/strong> [6,5,4,1,3,2,1]\n<\/pre>\n\n\n\n<p><strong>Constraints:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>1 &lt;= n &lt;= 10^5<\/code><\/li><li><code>edges.length == n - 1<\/code><\/li><li><code>edges[i].length == 2<\/code><\/li><li><code>0 &lt;= a<sub>i<\/sub>,&nbsp;b<sub>i<\/sub>&nbsp;&lt; n<\/code><\/li><li><code>a<sub>i<\/sub>&nbsp;!=&nbsp;b<sub>i<\/sub><\/code><\/li><li><code>labels.length == n<\/code><\/li><li><code>labels<\/code>&nbsp;is consisting of only of lower-case English letters.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Solution: Post order traversal + hashtable<\/strong><\/h2>\n\n\n\n<p>For each label, record the count. When visiting a node, we first record the current count of its label as before, and traverse its children, when done, increment the current count, ans[i] = current &#8211;  before.<\/p>\n\n\n\n<p>Time complexity: O(n)<br>Space complexity: O(n)<\/p>\n\n\n\n<div class=\"responsive-tabs\">\n<h2 class=\"tabtitle\">C++<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"C++\">\n\/\/ Author: Huahua\nclass Solution {\npublic:\n  vector<int> countSubTrees(int n, vector<vector<int>>& edges, \n                            string_view labels) {\n    vector<vector<int>> g(n);    \n    for (const auto& e : edges) {\n      g[e[0]].push_back(e[1]);\n      g[e[1]].push_back(e[0]);\n    }\n    vector<int> seen(n);\n    vector<int> count(26);\n    vector<int> ans(n);\n    function<void(int)> postOrder = [&](int i) {\n      if (seen[i]++) return;\n      int before = count[labels[i] - 'a'];\n      for (int j : g[i]) postOrder(j);        \n      ans[i] = ++count[labels[i] - 'a'] - before;\n    };\n    postOrder(0);\n    return ans;\n  }\n};\n<\/pre>\n\n<\/div><h2 class=\"tabtitle\">Java<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"java\">\n\/\/ Author: Huahua\nclass Solution {\n  private List<List<Integer>> g;\n  private String labels;\n  private int[] ans;\n  private int[] seen;\n  private int[] count;\n  \n  public int[] countSubTrees(int n, int[][] edges, String labels) {\n    this.g = new ArrayList<List<Integer>>(n);\n    this.labels = labels; \n    for (int i = 0; i < n; ++i)\n      this.g.add(new ArrayList<Integer>());\n    for (int[] e : edges) {\n      this.g.get(e[0]).add(e[1]);\n      this.g.get(e[1]).add(e[0]);\n    }\n    this.ans = new int[n];\n    this.seen = new int[n];\n    this.count = new int[26];\n    this.postOrder(0);\n    return ans;\n  }\n  \n  private void postOrder(int i) {\n    if (this.seen[i]++ > 0) return;\n    int before = this.count[this.labels.charAt(i) - 'a'];\n    for (int j : this.g.get(i)) this.postOrder(j);\n    this.ans[i] = ++this.count[this.labels.charAt(i) - 'a'] - before;    \n  }\n}\n<\/pre>\n\n<\/div><h2 class=\"tabtitle\">Python3<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"python\">\n# Author: Huahua\nclass Solution:\n  def countSubTrees(self, n: int, edges: List[List[int]], \n                    labels: str) -> List[int]:\n    g = [[] for _ in range(n)]\n    for u, v in edges:\n      g[u].append(v)\n      g[v].append(u)\n    seen = [False] * n\n    count = [0] * 26\n    ans = [0] * n\n    def postOrder(i):\n      if seen[i]: return\n      seen[i] = True\n      before = count[ord(labels[i]) - ord('a')]\n      for j in g[i]: postOrder(j)\n      count[ord(labels[i]) - ord('a')] += 1\n      ans[i] = count[ord(labels[i]) - ord('a')] - before\n    postOrder(0)\n    return ans\n<\/pre>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Given a tree (i.e. a connected, undirected graph that has no cycles) consisting of&nbsp;n&nbsp;nodes numbered from&nbsp;0&nbsp;to&nbsp;n &#8211; 1&nbsp;and exactly&nbsp;n &#8211; 1&nbsp;edges. The&nbsp;root&nbsp;of the tree is&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[45],"tags":[82,56,17,28],"class_list":["post-7119","post","type-post","status-publish","format-standard","hentry","category-tree","tag-hashtable","tag-postorder","tag-recursion","tag-tree","entry","simple"],"_links":{"self":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/7119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/comments?post=7119"}],"version-history":[{"count":2,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/7119\/revisions"}],"predecessor-version":[{"id":7121,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/7119\/revisions\/7121"}],"wp:attachment":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/media?parent=7119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/categories?post=7119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/tags?post=7119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}