1519. 子樹中標籤相同的節點數-無向圖、樹-中等難度
問題描述
給你一棵樹(即,一個連通的無環無向圖),這棵樹由編號從 0 到 n - 1 的 n 個節點組成,且恰好有 n - 1 條 edges 。樹的根節點為節點 0 ,樹上的每一個節點都有一個標籤,也就是字串 labels 中的一個小寫字元(編號為 i 的 節點的標籤就是 labels[i] )
邊陣列 edges 以 edges[i] = [ai, bi] 的形式給出,該格式表示節點 ai 和 bi 之間存在一條邊。
返回一個大小為 n 的陣列,其中 ans[i] 表示第 i 個節點的子樹中與節點 i 標籤相同的節點數。
樹 T 中的子樹是由 T 中的某個節點及其所有後代節點組成的樹。
示例 1:
輸入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = "abaedcd"
輸出:[2,1,1,1,1,1,1]
解釋:節點 0 的標籤為 'a' ,以 'a' 為根節點的子樹中,節點 2 的標籤也是 'a' ,因此答案為 2 。注意樹中的每個節點都是這棵子樹的一部分。
節點 1 的標籤為 'b' ,節點 1 的子樹包含節點 1、4 和 5,但是節點 4、5 的標籤與節點 1 不同,故而答案為 1(即,該節點本身)。
示例 2:
輸入:n = 4, edges = [[0,1],[1,2],[0,3]], labels = "bbbb"
解釋:節點 2 的子樹中只有節點 2 ,所以答案為 1 。
節點 3 的子樹中只有節點 3 ,所以答案為 1 。
節點 1 的子樹中包含節點 1 和 2 ,標籤都是 'b' ,因此答案為 2 。
節點 0 的子樹中包含節點 0、1、2 和 3,標籤都是 'b',因此答案為 4 。
示例 3:
輸入:n = 5, edges = [[0,1],[0,2],[1,3],[0,4]], labels = "aabab"
輸出:[3,2,1,1,1]
示例 4:
輸入:n = 6, edges = [[0,1],[0,2],[1,3],[3,4],[4,5]], labels = "cbabaa"
輸出:[1,2,1,1,2,1]
輸入:n = 7, edges = [[0,1],[1,2],[2,3],[3,4],[4,5],[5,6]], labels = "aaabaaa"
輸出:[6,5,4,1,3,2,1]
提示:
1 <= n <= 10^5
edges.length == n - 1
edges[i].length == 2
0 <= ai,bi < n
ai !=bi
labels.length == n
labels 僅由小寫英文字母組成
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/number-of-nodes-in-the-sub-tree-with-the-same-label
解答
/* 只需要遍歷一遍樹,從根節點依次返回字母,在上層做累加。 把無向圖當做樹遍歷的時候,要注意父子節點的順序,可以用visited陣列來表示某個節點是否訪問過,先訪問的必然是根節點。 */ class Solution { Map<Integer,List<Integer>> g; String labels; int[] result; public int[] dfs(int root, boolean[] visited){ visited[root] = true; int[] count = new int[26];//26個字母 count[labels.charAt(root) - 'a']++; for(int next:g.get(root)){ if(!visited[next]){ int[] res = dfs(next, visited); for(int i=0;i<26;i++)count[i]+=res[i]; } } result[root] = count[labels.charAt(root) - 'a']; return count; } public int[] countSubTrees(int n, int[][] edges, String labels) { this.labels = labels; g = new HashMap<Integer,List<Integer>>(); for(int i=0;i<n;i++)g.put(i,new ArrayList<Integer>()); for(int[] temp:edges){ g.get(temp[0]).add(temp[1]); g.get(temp[1]).add(temp[0]); } result = new int[n]; boolean[] visited = new boolean[n]; dfs(0, visited); return result; } } /*超時程式碼 class Solution { Map<Integer,List<Integer>> g; Map<Integer,Character> label; Map<Integer,Integer> count; List<Integer> visited; public int dfs(int start, char c){ int num = 0; count.put(start,0); if(c == label.get(start))num = 1; for(int i:g.get(start)){ if(!visited.contains(i) && count.get(i) == 1)num += dfs(i, c); } count.put(start,1); return num; } public int[] countSubTrees(int n, int[][] edges, String labels) { g = new HashMap<Integer,List<Integer>>(); label = new HashMap<Integer,Character>(); count = new HashMap<Integer,Integer>(); if(n == 1){ int[] res = {1}; return res; } for(int i=0;i<n;i++){ g.put(i,new ArrayList<Integer>()); label.put(i,labels.charAt(i)); count.put(i,1); } for(int[] temp:edges){ g.get(temp[0]).add(temp[1]); g.get(temp[1]).add(temp[0]); } int[] res = new int[n]; visited = new ArrayList<Integer>(); List<Integer> todo = new ArrayList<Integer>(); todo.add(0); while(!todo.isEmpty()){ for(int i=0;i<todo.size();i++){ visited.add(todo.get(i)); res[todo.get(i)] = dfs(todo.get(i), label.get(todo.get(i))); for(int j:g.get(todo.get(i)))if(!visited.contains(j))todo.add(j); todo.remove(i); } } return res; } } */