每日一题
2003. 每棵子树内缺失的最小基因值(hard)
主要思路是寻找两种树, 一类是子树基因包含1的结点(那么ans其子树的父节点的缺失的基因值为1); 另外一类是子树基因不包含1的结点, 那么需要去遍历其子树的所有基因值。
class Solution {
// 寻找的是 每个节点为根的子树中, 权重在 [1, n+1]范围内的最小缺失值, 而不是nums中的缺失值
// 把结点分成两类, 一类是子树基因包含值为1的节点, 一类是子树基因不包含值为1(遍历其子树的所有基因值)
List<List<Integer>> children; // 子节点序列
Set<Integer> genSet; //基因值序列
// 结点值[0,n-1], 基因值
public int[] smallestMissingValueSubtree(int[] parents, int[] nums) {
int n = parents.length;
children = new ArrayList<>();
for(int i = 0; i<n; i++){
children.add(new ArrayList<>()); // 生成每个节点的子节点序列
}
int getOnePathNode = nums[0] == 1 ? 0 : -1;
for(int i = 1; i<n; i++){
children.get(parents[i]).add(i); // 增加子节点
if(nums[i] == 1) getOnePathNode = i; // 找到基因值为1的节点
}
int[] ans = new int[n];
Arrays.fill(ans, 1); // 初始化, 值全为1
int lastNode = -1; // 上一个处理的节点, 其子树无需处理
int missVal = 2; // 基因值为1节点 在路径上的节点, 最小缺失值从2开始找
genSet = new HashSet<>();
while(getOnePathNode != -1){
dfs(getOnePathNode, lastNode, nums); // 搜索以getOnePathNode为根的
while(genSet.contains(missVal)) missVal++;
ans[getOnePathNode] = missVal; // 当前节点的缺失值 ([1,n])
lastNode = getOnePathNode; // lastNode 为上一个搜索过的结点, 其子树已经搜索过
getOnePathNode = parents[getOnePathNode]; // (递归弹栈) 向上去遍历, 更新父节点缺失的基因值
}
return ans;
}
void dfs(int node, int getOnePathNode, int[] nums){ // 深搜每个子树
genSet.add(nums[node]); // 添加子节点的基因值
for(int child: children.get(node)){
if(child == getOnePathNode) continue; // 说明已经搜索过, continue 跳过当前循环
dfs(child, getOnePathNode, nums); // 搜索其子树
}
}
}
此解法是参考LeetCode上公开的解法, 希望大佬们能够批评指正, 谢谢!