leetcode链接
https://leetcode.cn/problems/smallest-missing-genetic-value-in-each-subtree/description/
题目描述
示例
思路
寻求缺失的最小基因数,其实就是找到以这个节点为根的树的基因值数组中不存在的最小的那个数
就比如[2,4,5]中最小基因数是1,[1,3,5]中最小基因数是2
我们拿示例2来研究题目
最直接最简单的暴力想法,我们直接以每一个节点做根,然后求出他们的基因数组,最后在找出他们的最小的缺失基因,不过说着容易,其实做起来也挺麻烦的,而且这个复杂度一定很高,所以我们再观察下题目
我们其实可以发现一个很厉害的数——1,如果这个基因数组中不存在1的话,不管什么情况,这个基因数组的确实的最小基因数就是1了,其他任何数都不具有这种独一无二的性质,所以我们其实可以找包含基因数1的那些树,然后求他们的基因数组就可以了,对于不包含基因数1的那些树,他们缺失的最小基因数一定是1呀。
到这里其实我们就已经有收获了,我们只需要找到包含基因数为1的节点的树就可以了,其他的最小缺失基因数都是1
怎么找呢?,从0节点往下找吗?这样不又变成原来的样子了,再一看题目给我们了parents[]数组,这不刚好,我们从基因数1的节点开始找,然后找他爸爸,然后找他爸爸的爸爸,知道节点0,找到的这些节点都是包含基因数为1节点的节点啊(绕)下边看代码
python3代码
class Solution:
def smallestMissingValueSubtree(self, parents: List[int], nums: List[int]) -> List[int]:
n=len(parents)
res=[1]*n #先做初始化,把所有的缺失最小基因数都当1
if 1 not in nums: # 如果这个总的树里根本没1,那其实就不用看了,直接返回res
return res
#因为我们要找到那些包含基因数1的树,而题目给的parents数组并不方便我们查找某个节点的孩子,所以在这里我们在建一个children数组,
#用来表示某个i节点的孩子是谁,当然,一个节点的孩子不一定只有一个,所以我们创建的数组是这样形式的[[],[]]
children=[[] for in range(n)]
for i in range(1,n): # 因为0节点没有父亲,也就是没有人的孩子是0,所以我们从1节点开始
children[parents[i]].append(i) #原来是节点i的父亲是parents[i],我们只需要变成父亲parents[i]的孩子是children[parents[i]]也就是i即可
tag=set() # tag其实就是基因数组,我们写成set()仅仅是因为set()查找某个元素是否存在更快,其实写成数组也行
#这里要进行一个深度遍历,其实就是找到以node为根的树而已,然后把每个节点的基因数加入到tag里
def dfs(node: int)-> None:
tag.add(nums[node])
for son in children[node]:
if nums[son] not in tag: #对于我们已经存在在tag里的那些基因数,就不需要重复添加了,只添加不存在的
dfs(son)
node=nums.index(1) #先获得最开始的那个基因数为1的节点
tmp=2 #因为现在找的树都包含基因数1的节点,所以最小的缺失基因数最小也只能是2咯
while node>=0: #遍历终止条件就是到0节点
dfs(node)
while tmp in tag: #这里是为了找出最小的缺失基因数,当tmp没缺失时,就把他+1,早晚找到缺失的tmp
tmp+=1
res[node]=tmp # 加进来res就可以咯
node=parents[node] #找完这个节点的最小缺失基因数,就该找他爸爸的了
return res
这个解法我一开始也是没想出来,多亏了力扣题解中 灵茶山艾府 大佬的图文,赞