class Solution {
public:
vector<int> findSubtreeSizes(vector<int>& parent, string s) {
}
};
3331. 修改后子树的大小
给你一棵 n
个节点且根节点为编号 0 的树,节点编号为 0
到 n - 1
。这棵树用一个长度为 n
的数组 parent
表示,其中 parent[i]
是第 i
个节点的父亲节点的编号。由于节点 0 是根,parent[0] == -1
。
给你一个长度为 n
的字符串 s
,其中 s[i]
是节点 i
对应的字符。
对于节点编号从 1
到 n - 1
的每个节点 x
,我们 同时 执行以下操作 一次 :
x
最近 的祖先节点 y
,且 s[x] == s[y]
。y
不存在,那么不做任何修改。x
与它父亲节点之间的边 删除 ,在 x
与 y
之间连接一条边,使 y
变为 x
新的父节点。请你返回一个长度为 n
的数组 answer
,其中 answer[i]
是 最终 树中,节点 i
为根的子树的 大小 。
一个 子树 subtree
指的是节点 subtree
和它所有的后代节点。
示例 1:
输入:parent = [-1,0,0,1,1,1], s = "abaabc"
输出:[6,3,1,1,1,1]
解释:
节点 3 的父节点从节点 1 变为节点 0 。
示例 2:
输入:parent = [-1,0,4,0,1], s = "abbba"
输出:[5,2,1,1,1]
解释:
以下变化会同时发生:
提示:
n == parent.length == s.length
1 <= n <= 105
i >= 1
,都有 0 <= parent[i] <= n - 1
。parent[0] == -1
parent
表示一棵合法的树。s
只包含小写英文字母。原站题解
java 解法, 执行用时: 143 ms, 内存消耗: 86.2 MB, 提交时间: 2024-11-09 00:09:55
class Solution { public int[] findSubtreeSizes(int[] parent, String s) { int n = parent.length; List<Integer>[] g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>()); for (int i = 1; i < n; i++) { g[parent[i]].add(i); } int[] size = new int[n]; int[] ancestor = new int[26]; Arrays.fill(ancestor, -1); dfs(0, g, s.toCharArray(), ancestor, size); return size; } private void dfs(int x, List<Integer>[] g, char[] s, int[] ancestor, int[] size) { size[x] = 1; int sx = s[x] - 'a'; int old = ancestor[sx]; ancestor[sx] = x; for (int y : g[x]) { dfs(y, g, s, ancestor, size); int anc = ancestor[s[y] - 'a']; size[anc < 0 ? x : anc] += size[y]; } ancestor[sx] = old; // 恢复现场 } }
golang 解法, 执行用时: 98 ms, 内存消耗: 42.5 MB, 提交时间: 2024-11-09 00:09:36
func findSubtreeSizes(parent []int, s string) []int { n := len(parent) g := make([][]int, n) for i := 1; i < n; i++ { p := parent[i] g[p] = append(g[p], i) } size := make([]int, n) ancestor := [26]int{} for i := range ancestor { ancestor[i] = -1 } var dfs func(int) dfs = func(x int) { size[x] = 1 sx := s[x] - 'a' old := ancestor[sx] ancestor[sx] = x for _, y := range g[x] { dfs(y) anc := ancestor[s[y]-'a'] if anc < 0 { anc = x } size[anc] += size[y] } ancestor[sx] = old // 恢复现场 } dfs(0) return size }
python3 解法, 执行用时: 943 ms, 内存消耗: 63.1 MB, 提交时间: 2024-11-09 00:09:09
class Solution: def findSubtreeSizes2(self, parent: List[int], s: str) -> List[int]: n = len(parent) g = [[] for _ in range(n)] for i in range(1, n): g[parent[i]].append(i) ancestor = defaultdict(lambda: -1) def rebuild(x: int) -> None: old = ancestor[s[x]] ancestor[s[x]] = x for i in range(len(g[x])): y = g[x][i] if (anc := ancestor[s[y]]) != -1: g[anc].append(y) g[x][i] = -1 # -1 表示删除 y rebuild(y) ancestor[s[x]] = old # 恢复现场 rebuild(0) size = [1] * n # 注意这里已经把 1 算进去了 def dfs(x: int) -> None: for y in g[x]: if y != -1: # y 没被删除 dfs(y) size[x] += size[y] dfs(0) return size # 一次dfs def findSubtreeSizes(self, parent: List[int], s: str) -> List[int]: n = len(parent) g = [[] for _ in range(n)] for i in range(1, n): g[parent[i]].append(i) size = [1] * n ancestor = defaultdict(lambda: -1) def dfs(x: int) -> None: old = ancestor[s[x]] ancestor[s[x]] = x for y in g[x]: dfs(y) anc = ancestor[s[y]] size[x if anc < 0 else anc] += size[y] ancestor[s[x]] = old # 恢复现场 dfs(0) return size