leetcode 2127.参加会议的最多员工数 --随笔

力扣链接

https://leetcode.cn/problems/maximum-employees-to-be-invited-to-a-meeting/

题目描述

leetcode 2127.参加会议的最多员工数 --随笔_第1张图片

示例

leetcode 2127.参加会议的最多员工数 --随笔_第2张图片
leetcode 2127.参加会议的最多员工数 --随笔_第3张图片 leetcode 2127.参加会议的最多员工数 --随笔_第4张图片

思路

本题题目倒是很好理解,也很容易知道要干嘛的,但是却不好写 写这道题前我们先了解一个东西——基环树 leetcode 2127.参加会议的最多员工数 --随笔_第5张图片
当基环只有两个节点的时候 leetcode 2127.参加会议的最多员工数 --随笔_第6张图片 很关键的是,基环节点是不是2个会有很大区别,我们看 当节点大于2个时候,这个环就不能插入其他人了,为啥呢,我们试试任意两个节点a,b之间插入一个c,我们知道,a,b之间是一条有向边,也就是要不就是a喜欢b,要不就是b喜欢a,这样才能开会,但如果你把c插进去,就会产生a不能和他喜欢的b坐一起(或者说b不能和他喜欢的a在一起),这样就不能达成题目要求了。所以说,当节点大于2个的时候,这个基环树上最大员工数量就是基环长度,我们记作max_ring_size
当节点等于两个的时候就不一样了,我们可以插到两边呀,比如这个图 leetcode 2127.参加会议的最多员工数 --随笔_第7张图片
0和1两边可以插入其他的节点,很明显,对于多个基环长度等于 2的基环树,每个基环树所对应的链,都可以拼在其余链的末尾,因此可以将这些链全部拼成一个圆桌,其大小记作 sumChainSize 由于给的输入数据可能含有多种基环树,所以最终的答案就是max(maxRingSize,sumChainSize)

python3代码

class Solution:
    def maximumInvitations(self, favorite: List[int]) -> int:
        n = len(favorite)
        deg = [0] * n          #这个deg用来统计第i个人被多少人喜欢
        for f in favorite:
            deg[f] += 1  # 统计基环树每个节点的入度

        max_depth = [1] * n   #这个用来统计树的深度
        q = deque(i for i, d in enumerate(deg) if d == 0) #这个q队列存储的是那些树枝中最下层的节点,他们没有入度,下面这段代码主要就是为了减去所有树枝,只留基环
        while q:  # 拓扑排序,剪掉图上所有树枝
            x = q.popleft()     #先去掉一个一个节点
            y = favorite[x]  # 找到这个去除的节点喜欢谁
            max_depth[y] = max_depth[x] + 1  #这个被喜欢的节点的深度当然等于x的深度+1
            deg[y] -= 1    #因为x被减去了,把y的被喜欢-1
            if deg[y] == 0: #如果没人喜欢y了,y就成了树枝中最下层的节点,给他加入q,然后马上就给他删了
                q.append(y)

        max_ring_size = sum_chain_size = 0  #这里前边介绍了
        for i, d in enumerate(deg):   #这里就是为了找到最大的基环长度
            if d == 0: continue   #没人喜欢,肯定不在环中,直接下一个

            # 遍历基环上的点
            deg[i] = 0  # 随便找一个有人喜欢的i,将基环上的点的入度标记为 0,避免重复访问
            ring_size = 1  # 基环长度
            x = favorite[i]  #找到i喜欢谁
            while x != i: #因为是一个环,就一直重复这个过程,知道最后转到自己,这样就知道环的长度了
                deg[x] = 0  # 将基环上的点的入度标记为 0,避免重复访问
                ring_size += 1
                x = favorite[x]

            if ring_size == 2:  # 基环长度为 2
                sum_chain_size += max_depth[i] + max_depth[favorite[i]]  # 累加两条最长链的长度
            else:
                max_ring_size = max(max_ring_size, ring_size)  # 取所有基环长度的最大值
        return max(max_ring_size, sum_chain_size)

本文是参考leetcode题解中灵茶山艾府写成的,题目很难,题解也不好理解,所以我结合自己的理解写了这一篇文章,当然,最好还是自己debug一下看看过程,就很清楚

本文由博客一文多发平台 OpenWrite 发布!

你可能感兴趣的:(leetcode)