青训营X豆包MarsCode 技术训练营第六课 | 豆包MarsCode AI 刷题

23 阅读4分钟

这段代码是一个解决问题的实现,问题可以概括为:给定一个整数列表 airports,其中每个元素代表一个机场所属的航空公司编号,我们需要计算从第一个机场(索引为0)到最后一个机场(索引为n-1)所需的最少“起飞次数”。这里的“起飞次数”可以理解为从一个机场到达另一个机场的最小步骤数,其中步骤可以包括直接前往相邻的机场(索引相邻)或者前往同一航空公司下的其他机场(不论距离)。下面是对代码的详细解析。 代码整体结构代码主要由几个部分组成: 输入处理:通过遍历 airports 列表,使用 defaultdict 构建一个 company_map,这个字典将每个航空公司编号映射到属于该航空公司的所有机场的索引列表。广度优先搜索(BFS)初始化:使用 deque 作为队列,初始时将第一个机场(索引0)及其起飞次数0加入队列,同时标记该机场为已访问。 BFS 循环:在队列不为空的情况下,不断从队列中取出元素(当前机场索引和起飞次数),检查是否到达最后一个机场,如果到达则返回当前的起飞次数。如果没有到达,则分别尝试访问相邻机场和同一航空公司的其他机场,将它们加入队列,并标记为已访问。防止重复访问:为了避免重复访问同一航空公司的机场导致无限循环,每次访问完一个航空公司的所有机场后,清空该航空公司在 company_map 中的记录。详细解析输入处理: company_map 是一个 defaultdict(list),它允许我们为每个航空公司编号快速添加机场索引。遍历 airports 列表,使用 enumerate 获取每个机场的索引和对应的航空公司编号,然后将索引添加到对应航空公司编号的列表中。 BFS 初始化:使用 deque 作为队列是因为它支持快速的从两端添加和删除元素,这对于BFS来说是非常有用的。初始时将 (0, 0) 加入队列,表示从第一个机场(索引0)出发,起飞次数为0。使用 set 作为 visited 记录已访问的机场,因为 set 的查找和插入操作都是平均时间复杂度为O(1)的。 BFS 循环:每次从队列中取出一个元素(当前机场索引和起飞次数)。检查是否到达终点(即最后一个机场),如果是则返回当前的起飞次数。尝试访问相邻机场(索引减1和加1),如果索引在合法范围内且该机场未被访问过,则将其加入队列,并标记为已访问。尝试访问同一航空公司的其他机场,这通过查找 company_map[airports[index]] 实现。对于每个未访问过的同一航空公司的机场,将其加入队列,并标记为已访问。清空该航空公司在 company_map 中的记录,防止后续重复访问。这是因为在一次BFS迭代中,同一航空公司的所有机场都可以被看作是从当前机场一步可达的,因此不需要再次考虑它们作为中间节点。关键点广度优先搜索(BFS):BFS是一种遍历或搜索树(或图)的算法,它从根(或起始节点)开始,首先探索所有相邻的节点,然后再逐层向外扩展,直到找到目标节点或遍历完所有节点。BFS非常适合用于求解最短路径问题,因为它总是首先到达最近的节点。防止重复访问:在处理同一航空公司的机场时,必须小心避免重复访问,否则会导致无限循环。通过清空已访问过的航空公司的记录,确保每个机场只被访问一次。数据结构的选择:使用 deque 作为队列,set 作为已访问集合,以及 defaultdict 作为航空公司到机场索引的映射,都是基于性能考虑的选择。这段代码是一个典型的图搜索问题解决方案,展示了如何结合具体问题的特点(如允许通过航空公司直接跳转)来设计和实现算法。