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

【力扣】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] * nfor i in range(n):indeg[favorite[i]] += 1used = [False] * nf = [1] * nq = deque(i for i in range(n) if indeg[i] == 0)while q:u = q.popleft()used[u] = Truev = favorite[u]# 状态转移f[v] = max(f[v], f[u] + 1)indeg[v] -= 1if indeg[v] == 0:q.append(v)# ring 表示最大的环的大小# total 表示所有环大小为 2 的「基环内向树」上的最长的「双向游走」路径之和ring = total = 0for i in range(n):if not used[i]:j = favorite[i]# favorite[favorite[i]] = i 说明环的大小为 2if favorite[j] == i:total += f[i] + f[j]used[i] = used[j] = True# 否则环的大小至少为 3,我们需要找出环else:u = icnt = 0while True:cnt += 1u = favorite[u]used[u] = Trueif u == i:breakring = 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.hqwc.cn/news/156311.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

干货分享 | 一分钟带你了解TSMaster小程序编辑代码智能提示功能

本文给大家带来TSMaster小程序编辑的新功能,其中主要包含:代码编辑智能提示功能、可用外部代码编辑器编辑小程序代码并同步。 本文关键字:C小程序、Python小程序、代码智能提示、外部代码编辑器、Visual Studio 目录/Catalog ● TSMaster的…

急诊医学科常用评估量表汇总,建议收藏!

根据急诊医学科医生的量表使用情况,笔者整理了10个急诊医学科常用量表,可在线评测直接出结果,可转发使用,可生成二维码使用,可创建项目进行数据管理,有需要的小伙伴赶紧收藏! 1.急性生理学与慢性…

柯桥专升本学校,自考本科文凭的价值如何?

自考本科文凭的价值如何? 自考本科学历是通过独立学习和考试获得的一种本科学历。对于自考本科学历的价值,很多人感到困惑,那么究竟自考本科学历有多大的价值呢? 首先,在就业市场上,自考本科学历具有一定的竞争力。随…

TensorFlow案例学习:简单的音频识别

前言 以下内容均来源于官方教程:简单的音频识别:识别关键字 音频识别 下载数据集 下载地址:http://storage.googleapis.com/download.tensorflow.org/data/mini_speech_commands.zip 可以直接浏览器访问下载。 下载完成后将其解压到项目…

libgdx实现淡入淡出过渡

libgdx实现淡入淡出过渡 libgdx实现淡入淡出过渡&#xff0c;环境jdk17、libgdx 1.12.02023年11月1日11:02:50最新 依赖 <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target>&…

LV.12 D13 UART实验 学习笔记

一、UART帧格式详解 UART Universal Asynchronous Receiver Transmitter 即 通用异步收发器&#xff0c;是一种通用的串行、异步通信总线 该总线有两条数据线&#xff0c;可以实现全双工的发送和接收&#xff0c;在嵌入式系统中常用于主机与辅助设备之间的通信。 通…

Day42 力扣动态规划 :123.买卖股票的最佳时机III |188.买卖股票的最佳时机IV

Day42 力扣动态规划 :123.买卖股票的最佳时机III &#xff5c;188.买卖股票的最佳时机IV 123.买卖股票的最佳时机III第一印象看完题解的思路dp数组&#xff1a;递推公式&#xff1a;初始化遍历顺序 实现中的困难感悟代码 188.买卖股票的最佳时机IV第一印象初始化递推公式看完题…

算法通过村第十八关-回溯|青铜笔记|什么叫回溯(后篇)

文章目录 前言回溯热身问题输出二叉树的所有路径&#xff1a;路径总和问题&#xff1a; 总结 前言 提示&#xff1a;今夜思量千条路&#xff0c;明朝依旧卖豆腐。 --谚语 回溯是非常重要的算法思想之一&#xff0c;主要解决一些暴力枚举也搞不定的问题&#xff08;这里埋个坑&a…

汽车配件商城小程序制作 | 汽车配件售卖,高门槛但高利润

通过汽车配件商城小程序给别人的供货&#xff0c;利润可高达60%&#xff0c;但甚少有人关注汽车配件销售的行业。具体情况是怎么样的呢&#xff0c;下面给大家简单分析。 据数据显示&#xff0c;国内有4亿多辆汽车&#xff0c;这些汽车坏了要修&#xff0c;也要偶尔进行保养&am…

集成测试、单元测试、系统测试之间的关系和区别

前言 为了使软件正常工作&#xff0c;所有单元都应集成在一起并正常运行。集成测试就像是要求不同工种的工人修建一个房子&#xff0c;希望他们都团结协作。如何判断他们在一起是否可以按照计划完成建设呢&#xff1f;唯一了解的方法是通过将它们全部拉在一起并测试它们如何相互…

正则表达式续篇

位置锚定&#xff1a; ^:行首锚定&#xff0c;表示以什么为开头 例如&#xff1a; $:行尾锚定&#xff0c;表示以什么为结尾 例如&#xff1a; ^&#xff1a;匹配的是空行 例如&#xff1a; ^root$&#xff1a;匹配整行&#xff0c;而且整行只能有这一个字符串 实验&#x…

百度地图直接用的封装好的--自用vue的(每次项目都要有百度地图,还是搞个封装的差不多的以后可以直接拿来用)

自用的封装好的,有弹窗,轨迹回放,画点画地图 完整代码使用 百度地图的官方文档 百度地图必须的三个引用 完整代码 <template><AButton style"background-color: #3ba7ea;color: white;width: 100px;float: right" click"buttonClick">轨迹回放…