2003. 每棵子树内缺失的最小基因值 (困难,DFS,Set.update)

文章讨论了一个关于在给定父节点关系和基因值列表的场景中,如何通过深度优先搜索和集合操作优化找到每个子树中缺失的最小基因值。作者指出,原方法的时间复杂度为O(nlogn),但通过利用set的高效查找和不需排序的合并,最终优化到总时间复杂度为O(nlogn)。

在这里插入图片描述
困难,还是一如既往的不会做,但是得写写自己的想法

  1. 先从根节点开始作深度搜索,对于每一个以 node 为根的子树,我们返回该子树排序后的基因集合,类似与归并排序
  2. 显然在每次合并集合进行排序的时候我们就可以知道 node 子树内缺失的最小基因值
  3. 我是觉得时间复杂度就在 O(nlogn),顶多n之前多几个常数系数,但还是超时了

正解:

  1. set集合的查找是 O(1) 的,当通过 set1.update(set2) 来合并两个 set 时(其中 set1 比 set2 大),同时对树作 dfs 是 O(nlogn)
  2. 所以不用排序合并,直接从 node 节点的子树中的最大缺失的最小基因值开始找 node 树的缺失的最小基因值,这个过程是 O(n)
  3. 所以总共是 O(nlogn)
class Solution:
    def smallestMissingValueSubtree(self, parents: List[int], nums: List[int]) -> List[int]:
        n = len(parents)
        child = defaultdict(list)
        for i in range(n):
            if parents[i] == -1:
                continue
            child[parents[i]].append(i)
        
        ans = [1] * n

        def find(node):
            childs = [[nums[node]]]
            for c in child[node]:
                childs.append(find(c))
            
            l, ans[node] = sort0(childs)
            return l
            
        def sort0(ll):
            a, b = [], []
            if len(ll) > 2:
                a, _ = sort0(ll[:len(ll)//2])
                b, _ = sort0(ll[len(ll)//2:])
            elif len(ll) == 2:
                a = ll[0]
                b = ll[1]
            else:
                return ll[0], 1 if ll[0][0] != 1 else 2
            t = []
            m = 1
            while len(a) > 0 and len(b) > 0:
                if a[0] > b[0]:
                    if b[0] == m:
                        m += 1
                    t.append(b[0])
                    b.pop(0)
                else:
                    if a[0] == m:
                        m += 1
                    t.append(a[0])
                    a.pop(0)
            while len(a) > 0:
                if a[0] == m:
                    m += 1
                t.append(a[0])
                a.pop(0)
            while len(b) > 0:
                if b[0] == m:
                    m += 1
                t.append(b[0])
                b.pop(0)
            return t, m
        
        find(0)
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eyvr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值