【力扣】2127. (分类讨论 + 拓扑排序)参加会议的最多员工数

news2025/7/15 11:18:58

【力扣】2127. (分类讨论 + 拓扑排序)参加会议的最多员工数

文章目录

  • 【力扣】2127. (分类讨论 + 拓扑排序)参加会议的最多员工数
    • 1. 题目介绍
    • 2. 思路(**分类讨论 + 拓扑排序**)
    • 3. 解题代码
    • 4. Danger
    • 参考

1. 题目介绍

一个公司准备组织一场会议,邀请名单上有 n 位员工。公司准备了一张 圆形 的桌子,可以坐下 任意数目 的员工。

  • 要求:员工编号为 0 到 n - 1 。每位员工都有一位 喜欢 的员工,每位员工当且仅当他被安排在喜欢员工的旁边,他才会参加会议每位员工喜欢的员工 不会 是他自己

  • 给你一个下标从 0 开始的整数数组 favorite ,其中 favorite[i] 表示第 i 位员工喜欢的员工。

  • 请你返回参加会议的 最多员工数目 。

示例

  • 1
    在这里插入图片描述
  • 2
    在这里插入图片描述
  • 3
    在这里插入图片描述

提示
在这里插入图片描述

2. 思路(分类讨论 + 拓扑排序

首先需要简单了解一下 基环内向树。在了解了树的基础上来解释基环树——树加一条边使之成环(也就是说,在严格意义上来说,基环树并不是树,就像老婆饼没有老婆一样,基环树是个图)。首先它是一个有向图,它构成类似基环树的结构。

  • 最重要的特点就是每个点都有且只有一个出度,并且环外的节点方向指向环内。
    在这里插入图片描述

针对这道题,我们可以把每个员工看成图上的一个节点,如果员工 x 喜欢员工 y,就在从 x 对应的节点到 y 对应的节点连一条边,那么形成的图则是会由若干颗「基环内向树」组成,就是形如下图所示的结构:
在这里插入图片描述
原因如下:

  • 我们从任意一个节点 x 开始在图上进行「游走」,由于每个员工只有一位喜欢的员工,因此每个节点在图上只会有一条出边,即「游走」的过程是唯一的。由于图上有 n 个节点,因此在 n+1 步以内,一定会走到一个重复的节点,那么在第一次经过该节点之后,到第二次经过该节点之前的所有节点,以及该节点本身,就组成了一个环,如上图的蓝色节点所示。
  • 对于不在环上的节点,我们已经说明了从它们开始「游走」也一定会进入到环中。在到达环上的节点之前,它们不会重复经过节点(否则就有两个环了,我们可以证明一个连通分量中是不可能有两个环的:因为每个节点只有一条出边,因此如果有两个环并且它们连通,那么必然某个环上有一个点有两条出边,一条出边指向同一个环上的节点,另一条出边可以使得它到达另一个环,这就产生了矛盾),那么它们就形成了类似树的结构,如上图的绿色节点所示。
  • 需要注意的是,一个单独的环也是「基环内向树」,它是一种特殊情况,即没有绿色的节点。

思路与算法:既然我们知道了图由若干颗「基环内向树」组成,那么我们只需要计算每一颗「基环内向树」的哪一部分可以被安排参加会议,就可以来接这道题目。

  • 1)首先讨论特殊的情况,即一个单独的环(或若干个环),并且所有环的大小都 ≥3。可以发现,我们按照环上的顺序给对应的员工安排座位是满足要求的,因为对于每一个环上的员工,它喜欢的员工就在它的旁边。并且,我们必须安排环上的所有员工,因为如果有缺失,那么喜欢那位缺失了的员工的员工就无法满足要求了。
    • 但如果我们已经安排了某一个环上的所有员工,剩余的环就没有办法安排了。这是因为已经安排的那个环是没有办法被「断开」的:断开的本质就是相邻位置员工的缺失。因此,我们可以得出一个重要的结论:
      • 如果我们想安排大小 ≥3 的环,我们最多只能安排一个,并且环需要是完整的
  • 2)接下来是,形成的图是 环大小 ≥3 的「基环内向树」,如果我们安排了不在环上的节点,那么从该节点开始,我们需要不断安排当前节点喜欢的员工,这实际上就是「游走」的过程。
    • 而当我们游走到环上并到达环上最后一个未经过的节点时,该节点的下一个节点(即喜欢的员工)已经被安排过,所以最后一个未经过的节点就无法被安排(因为下一个节点不是他的喜欢节点),不满足要求。因此,我们不能安排任何不在环上的节点,只能安排在环上的节点,就得出了另一个的结论:
      • 所有环大小 ≥3 的「基环内向树」与一个大小相同(指环的部分)的环是等价的。
  • 3)最后,需要考虑大小 =2 的环或者「基环内向树」了。
    • 这里的特殊之处在于,大小 =2 的环可以安排多个:因为环上的两个点是互相喜欢的,因此只需要它们相邻即可,而没有其它的要求。
    • 而对于环大小 =2 的「基环内向树」,如果我们安排了不在环上的节点,那么游走完环上两个节点之后,同样是满足要求的,并且我们甚至可以继续延伸(反向「游走」),到另一个不在环上的节点为止。如下图所示,包含 X 的节点就是可以安排参加会议的节点。
      在这里插入图片描述
    • 并且同样地,对于每一棵环大小 =2 的「基环内向树」,我们都可以取出这样一条「双向游走」路径进行安排,它们之间不会影响。

综上所述,原问题的答案即为下面二者中的最大值:

  • 最大的环的大小;
  • 所有环大小 =2 的「基环内向树」上的最长的「双向游走」路径之和。

为了求解「基环内向树」上的最长的「双向游走」路径,我们可以使用拓扑排序 + 动态规划的方法。记 f[i] 表示到节点 i 为止的最长「游走」路径经过的节点个数,那么状态方程即为:
在这里插入图片描述

  • 即我们考虑节点 i 的上一个节点 j,在图中必须有从 j 到 i 的一条有向边,这样我们就可以从 j 转移到 i。如果不存在满足要求的 j(例如「基环内向树」退化成一个大小 =2 的环),那么 f[i]=1。状态转移可以和拓扑排序同时进行。
  • 在拓扑排序完成后,剩余没有被弹出过队列的节点就是环上的节点。我们可以找出每一个环。如果环的大小 ≥3,我们就用其来更新最大的环的大小;如果环的大小 =2,设环上的两个节点为 x 和 y,那么该「基环内向树」上最长的「双向游走」的路径长度就是 f[x]+f[y]。

时间复杂度:O(n)。图中有 n 个节点和 n 条边,拓扑排序需要的时间为 O(n),后续找出所有环的时间也为 O(n)。
空间复杂度:O(n)。我们需要若干个长度为 n 的数组。

3. 解题代码

class Solution:
    def maximumInvitations(self, favorite: List[int]) -> int:
        n = len(favorite)
        # 统计入度,便于进行拓扑排序
        indeg = [0] * n
        for i in range(n):
            indeg[favorite[i]] += 1
        
        used = [False] * n
        f = [1] * n
        q = deque(i for i in range(n) if indeg[i] == 0)
        
        while q:
            u = q.popleft()
            used[u] = True
            v = favorite[u]
            # 状态转移
            f[v] = max(f[v], f[u] + 1)
            indeg[v] -= 1
            if indeg[v] == 0:
                q.append(v)
        
        # ring 表示最大的环的大小
        # total 表示所有环大小为 2 的「基环内向树」上的最长的「双向游走」路径之和
        ring = total = 0
        for i in range(n):
            if not used[i]:
                j = favorite[i]
                # favorite[favorite[i]] = i 说明环的大小为 2
                if favorite[j] == i:
                    total += f[i] + f[j]
                    used[i] = used[j] = True
                # 否则环的大小至少为 3,我们需要找出环
                else:
                    u = i
                    cnt = 0
                    while True:
                        cnt += 1
                        u = favorite[u]
                        used[u] = True
                        if u == i:
                            break
                    ring = max(ring, cnt)
        
        return max(ring, total)

4. Danger

力扣(LeetCode)是领扣网络旗下专注于程序员技术成长和企业技术人才服务的品牌。源自美国硅谷,力扣为全球程序员提供了专业的IT技术职业化提升平台,有效帮助程序员实现快速进步和长期成长。此外,力扣(LeetCode)致力于解决程序员技术评估、培训、职业匹配的痛点,逐步引领互联网技术求职和招聘迈向专业化。

  • 据了解到的情况,Easy题和Medium 题在面试中比较常见,通常会以手写代码之类的形式出现,您需要对问题进行分析并给出解答,并于面试官进行交流沟通,有时还会被要求分析时间复杂度8与空间复杂度°,面试官会通过您对题目的分析解答,了解您对常用算法的熟悉程度和您的程序实现功底。
  • 而在一些对算法和程序实现功底要求较高的岗位,Hard 题也是很受到面试官的青睐,如果您在面试中成功Bug-Free出一道Hard题,我们相信您一定会给面试官留下很深刻的印象,并极大增加拿到Offer的概率,据相关人士统计,如果您在面试成功解出一道Hard题,拿不到Offer的概率无限接近于0。
  • 所以,力扣中Easy和Medium相当于面试中的常规题,而Hard 则相当于面试中较难的题,解出—道Hard题,Offer可以说是囊中之物。

参考

【1】https://leetcode.cn/problems/maximum-employees-to-be-invited-to-a-meeting/?envType=daily-question&envId=2023-11-01
【2】https://leetcode.cn/problems/maximum-employees-to-be-invited-to-a-meeting/solutions/1190222/can-jia-hui-yi-de-zui-duo-yuan-gong-shu-u8e8u/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1158709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么时间跟踪对企业和员工很重要?

时间是每个企业主最宝贵的资产。如果员工不能正确管理自己的时间,就会出现延误,项目也会超出预算。 为了让员工获得公平的时间补偿,就必须记录他们的工作时间。工时管理系统可以帮助企业和员工更好地组织工作、提高效率和生产力,…

100量子比特启动实用化算力标准!玻色量子重磅发布相干光量子计算机

2023年5月16日,北京玻色量子科技有限公司(以下简称“玻色量子”)在北京正大中心成功召开了2023年首场新品发布会,重磅发布了自研100量子比特相干光量子计算机——“天工量子大脑”。 就在3个月前,因“天工量子大脑”在…

redis 集群配置

1 . 存在的问题 单台redis容量限制,如何进行扩容?继续加内存、加硬件么?单台redis并发写量太大有性能瓶颈,如何解决?redis3.0中提供了集群可以解决这些问题。 2 . 什么是集群 redis集群是对redis的水平扩容&#xff…

Whisper 从0安装教程 windows

这里写自定义目录标题 Whisper 从0安装教程 windows安装过程安装python3.11安装Anaconda在Anaconda里面安装whisper安装 ffmpeg第一次运行whisper检查GPU 一些弯路 Whisper 从0安装教程 windows 因为需要把语音变成文字稿,问了做语言相关的朋友,决定使用…

基于51单片机的智能手机充电器设计

**单片机设计介绍,1660【毕设课设】基于51单片机和MAX1898的智能手机充电器设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 51单片机智能手机充电器设计介绍 51单片机智能手机充电器是一种可以实现智能快速充电的…

stm32中断

目录 简介 什么是NVIC 中断优先级 EXTI 简介 总结 hal库初始化代码 标准库初始化代码 简介 什么是中断?正常情况下,微处理器根据代码内容,按顺序执行指令。执行过程中,如果遇到其它紧急的事件需要处理,则先暂停当…

CodeWhisperer 初体验-手把手教导 给你飞一般的体验!

文章作者:燛衣 CodeWhisperer 有以下几个主要用途: 解决编程问题:CodeWhisperer 可以帮助您解决遇到的编程问题。您可以描述您的问题或需求,CodeWhisperer 将尽力提供相关的解决方案、代码示例或建议。无论您是遇到了语法错误、逻…

ardupilot开发 --- SLAM 篇

1. 视觉SLAM 1.1 深度相机的种类 结构光相机,如 Kinect1.0、RealSenseTOF相机,如 Kinect2.0双目相机,如 ZED详细参考:https://zhuanlan.zhihu.com/p/282776636 1.2 视觉SLAM算法 2D slam 与3D slam 应用场景有哪些不同&#x…

高通财报分析:恶劣环境将导致高通股价在财报后大幅下跌

来源:猛兽财经 作者:猛兽财经 总结: (1)根据我们的分析,高通(QCOM)的股价在上个季度下跌了近16%,预计在本季度财报后还将继续下跌。 (2)在恶劣的环境下,高通…

西门子精智触摸屏使用U盘下载程序时报错“出现严重错误,必须关机”处理办法

西门子精智触摸屏使用U盘下载程序时报错“出现严重错误,必须关机”处理办法 如下图所示,精智触摸屏使用U盘下载程序时报错: Application CTLPNL. EXE encountered a serious error and must shut down 出现这种情况时,可以尝试从以下几方面进行逐个排查: 断电重启,更换U盘…

知了汇智2024届“天府人才·校招行”启动,这些岗位急招...

知了汇智作为数字经济新业态下的产教融合服务型平台机构,大力构建企业与高校的交流平台,旗下全资子公司成都知聊人才服务有限公司,致力于为企业提供数字技术、数字营销方面的人才招聘、人才输送、人才定制等服务;为求职者提供个人…

三氧化二铁纳米片

(西)三氧化二铁纳米片 (安)名称:三氧化二铁纳米片 (瑞)CAS:1309-37-1 (禧)分子式:Fe2O3 (生)外观:白色粉末…

怎么让照片内存变小?三个方法轻松搞定!

让照片内存变小可以节省存储空间、提高传输速度、优化图片质量和降低流量消耗等,对于设备性能和用户体验都有积极的影响。下面介绍了三种简单有效的方法,一起来看看吧~ 方法一:通过嗨格式压缩大师压缩照片让内存变小 通过压缩照片&#xff0…

avi怎么转mp4?

avi怎么转mp4?如今市面上涌现了各种多样的视频格式,其中AVI作为一种音频视频交错格式,虽然使用较少但相对常见。它的优点在于占用空间较小,但画面质量并不是很出色。然而,AVI格式也存在一个明显的缺点,即兼…

企业软文推广的时机有哪些?媒介盒子告诉你

软文成本低、效果持续,能够为企业带来品牌曝光,实现品牌增值,但是企业也不是每时每刻都需要进行软文推广,接下来媒介盒子就告诉大家,企业进行软文推广的时机有哪些? 一、 为新品造势 一般企业发布新品时就…

基于区域边缘控制器的智慧管廊安全监测方案

区域边缘控制器是一种集成了PLC、网关、数据采集、协议兼容、多设备联动控制等丰富功能的智能设备,基于高性能工业级处理器,内置边缘计算策略和设备控制逻辑,从而代替PLC,实现对边缘物联网设备的智能自主感知和控制,适…

python实现MC协议(SLMP 3E帧)的TCP服务端(篇一)

python实现MC协议(SLMP 3E帧)的TCP服务端是一件稍微麻烦点的事情。它不像modbusTCP那样,可以使用现成的pymodbus模块去实现。但是,我们可以根据协议帧进行组包,自己去实现帧的格式,而这一切可以基于socket模…

高压放大器在电火花加工中的作用是什么

高压放大器在电火花加工中扮演着至关重要的角色。下面安泰电子将详细介绍高压放大器在电火花加工中的作用。 电火花加工是一种精密加工技术,广泛应用于制造业的模具制造、航空航天、汽车零部件等领域。它通过在工件表面产生高频电火花放电的方式,实现对材…

设计模式(22)享元模式

一、介绍: 1、定义:享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。 2、…

vue3中解析地址(address-parse插件的使用)

1.安装 npm install address-parse --save 2.使用 // 引入address-parse import AddressParse, { AREA, Utils } from "address-parse";const adressValue ref([])const getResolutionContent () > {const [result] AddressParse.parse(EnterpriseSalesDetai…