力扣题解815

大家好,欢迎来到无限大的频道。祝大家中秋节快乐​。

今日继续给大家带来力扣题解。

题目描述(困难)​:

公交路线

给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。

  • 例如,路线 routes[0] = [1, 5, 7] 表示第 0 辆公交车会一直按序列 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> ... 这样的车站路线行驶。

现在从 source 车站出发(初始时不在公交车上),要前往 target 车站。 期间仅可乘坐公交车。

求出 最少乘坐的公交车数量 。如果不可能到达终点车站,返回 -1 。

解题思路

  1. 图模型:

    • 将公交线路和站点视为图的节点和边。每个站点是一个节点,每条公交线路可以看作是连接多个站点的边。

    • 我们需要找出从 source 站点到 target 站点的最短路径(最少乘坐的公交车数量)。最短路径我们采用BFS算法

  2. 哈希映射:

    • 使用哈希映射(在这里是链表实现的数组)来存储每个站点对应的公交线路。这样可以快速查找经过某个站点的所有公交线路。

  3. 广度优先搜索(BFS):

    • 使用 BFS 来遍历图,因为 BFS 能够找到最短路径。

    • BFS 从起始站点开始,逐层访问所有相邻的节点(公交线路),直到找到目标站点。

详细步骤

  1. 检查起始和目标站点:

    • 如果 source 和 target 相同,直接返回 0,因为不需要乘坐公交车。

  2. 构建哈希映射:

    • 使用 createHashMap 创建一个大小为 MAX_STOPS 的哈希映射数组 stop_to_routes。

    • 遍历每条线路,将每个站点映射到经过该站点的线路上。

  3. BFS 初始化:

    • 创建一个队列 queue 来存储待访问的公交线路。

    • 使用 visitedRoutes 数组记录已访问的线路,使用 visitedStops 数组记录已访问的站点。

    • 将所有经过 source 的公交线路入队,并标记为已访问。

  4. BFS 遍历:

    • 记录当前层的大小 levelSize,并增加深度 depth。

    • 遍历当前层的所有线路:

    • 如果当前站点是 target,则返回当前深度(乘坐的公交车数量)。

    • 如果当前站点未被访问,标记为已访问,并将该站点所有经过的未访问线路入队。

    • 对于每条线路,遍历其经过的所有站点:

    • 使用 while 循环进行 BFS,只要队列不为空:

  5. 资源释放:

    • 如果遍历完所有线路仍未找到目标站点,释放所有动态分配的内存并返回 -1。

关键部分解释

  • 哈希映射的使用:

    • 通过哈希映射,将站点映射到线路,能够快速获取经过某个站点的所有公交线路,避免了重复遍历,提高了效率。

  • BFS 的实现:

    • BFS 的层次遍历特性确保了在找到目标站点时,返回的深度是最小的,即乘坐的公交车数量是最少的。

代码参考​:

// 定义结构用于保存每个站点经过的路线
typedef struct Node {int data;struct Node* next;
} Node;
​
Node** createHashMap(int size) {// 用于初始化动态大小的哈希表Node** map = (Node**)malloc(size * sizeof(Node*));for (int i = 0; i < size; i++) {map[i] = NULL;}return map;
}
​
void insertHashMap(Node** map, int key, int value) {// 将一个值插入到哈希表中Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = value;newNode->next = map[key];map[key] = newNode;
}
​
typedef struct {int *data;int front;int rear;int size;int capacity;
} Queue;
​
Queue* createQueue(int capacity) {// 初始化队列结构Queue* queue = (Queue*)malloc(sizeof(Queue));queue->capacity = capacity;queue->front = 0;queue->size = 0;queue->rear = capacity - 1;queue->data = (int*)malloc(capacity * sizeof(int));return queue;
}
​
int isFull(Queue* queue) {// 检查队列是否已满return (queue->size == queue->capacity);
}
​
int isEmpty(Queue* queue) {// 检查队列是否为空return (queue->size == 0);
}
​
void enqueue(Queue* queue, int item) {// 向队列中加入元素if (isFull(queue))return;queue->rear = (queue->rear + 1) % queue->capacity;queue->data[queue->rear] = item;queue->size = queue->size + 1;
}
​
int dequeue(Queue* queue) {// 从队列中移除元素if (isEmpty(queue))return -1;int item = queue->data[queue->front];queue->front = (queue->front + 1) % queue->capacity;queue->size = queue->size - 1;return item;
}
​
int numBusesToDestination(int** routes, int routesSize, int* routesColSize, int source, int target) {if (source == target) return 0;
​// Step 1: 使用哈希映射保存站点与线路的对应关系const int MAX_STOPS = 1000000;Node** stop_to_routes = createHashMap(MAX_STOPS);for (int i = 0; i < routesSize; i++) {for (int j = 0; j < routesColSize[i]; j++) {int stop = routes[i][j];insertHashMap(stop_to_routes, stop, i);}}
​// BFS初始化Queue* queue = createQueue(routesSize);int depth = 0;int* visitedRoutes = (int*)calloc(routesSize, sizeof(int));int* visitedStops = (int*)calloc(MAX_STOPS, sizeof(int));
​Node* current = stop_to_routes[source];while (current != NULL) {enqueue(queue, current->data);visitedRoutes[current->data] = 1;current = current->next;}
​while (!isEmpty(queue)) {int levelSize = queue->size;depth++;
​for (int i = 0; i < levelSize; i++) {int route = dequeue(queue);
​for (int j = 0; j < routesColSize[route]; j++) {int stop = routes[route][j];if (stop == target) {free(visitedRoutes);free(visitedStops);free(queue->data);free(queue);for (int k = 0; k < MAX_STOPS; k++) {Node* iter = stop_to_routes[k];while (iter) {Node* toFree = iter;iter = iter->next;free(toFree);}}free(stop_to_routes);
​return depth;}if (!visitedStops[stop]) {visitedStops[stop] = 1;Node* iter = stop_to_routes[stop];while (iter != NULL) {int nextRoute = iter->data;if (!visitedRoutes[nextRoute]) {enqueue(queue, nextRoute);visitedRoutes[nextRoute] = 1;}iter = iter->next;}}}}}
​// 资源释放free(visitedRoutes);free(visitedStops);free(queue->data);free(queue);for (int i = 0; i < MAX_STOPS; i++) {Node* iter = stop_to_routes[i];while (iter) {Node* toFree = iter;iter = iter->next;free(toFree);}}free(stop_to_routes);
​return -1;
}

时间复杂度:

  • 构建哈希映射: 对于每个站点,将其加入相应的线路列表中。总共需要遍历所有站点,即 O(sum(routesColSize))。

  • BFS搜索: 在最坏情况下,需要访问所有站点和所有线路。由于每个站点只会被访问一次,且每个线路也只会被访问一次,时间复杂度为 O(sum(routesColSize))。

  • 因此,整体时间复杂度为 O(sum(routesColSize))。

空间复杂度:

  • 哈希映射 stop_to_routes: 需要为每个站点存储经过的线路,最坏情况下为 O(sum(routesColSize))。

  • 队列: 最多需要存储所有线路,即 O(routesSize)。

  • 访问标记数组: visitedRoutes 大小为 O(routesSize),visitedStops 大小为 O(MAX_STOPS)。

  • 因此,整体空间复杂度为 O(sum(routesColSize) + routesSize + MAX_STOPS)。

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

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

相关文章

Python logging库(python日志库)Logger(记录器、收集器、采集器)、Handler(处理器)、Formatter(格式化器)、Log Level(日志级别)

文章目录 Python Logging库详解简介日志记录的基本概念1. Logger&#xff08;记录器&#xff09;&#xff1a;这是日志系统的入口点。每个记录器都有一个名称&#xff0c;并且记录器之间可以存在父子关系。2. Handler&#xff08;处理器&#xff09;&#xff1a;记录器将日志消…

网络安全-intigriti-0422-XSS-Challenge Write-up

目录 一、环境 二、解题 2.1看源码 一、环境 Intigriti April Challenge 二、解题 要求&#xff1a;弹出域名就算成功 2.1看源码 我们看到marge方法&#xff0c;肯定是原型链污染题目 接的是传参&#xff0c;我们可控的点在于qs.config和qs.settings&#xff0c;这两个可…

Java设计模式—面向对象设计原则(四) ----->接口隔离原则(ISP) (完整详解,附有代码+案例)

文章目录 3.4 接口隔离原则(ISP)3.4.1 概述3.4.2 案列 3.4 接口隔离原则(ISP) 接口隔离原则&#xff1a;Interface Segregation Principle&#xff0c;简称ISP 3.4.1 概述 客户端测试类不应该被迫依赖于它不使用的方法&#xff1b;一个类对另一个类的依赖应该建立在最小的接…

Invoke-Maldaptive:一款针对LDAP SearchFilter的安全分析工具

关于Invoke-Maldaptive MaLDAPtive 是一款针对LDAP SearchFilter的安全分析工具&#xff0c;旨在用于对LDAP SearchFilter 执行安全解析、混淆、反混淆和安全检测。 其基础是 100% 定制的 C# LDAP 解析器&#xff0c;该解析器处理标记化和语法树解析以及众多自定义属性&#x…

Excel图片批量插入单元格排版处理插件【图片大师】

为了方便大家在图片的插入排版的重复工作中解放出来&#xff0c;最近发布了一款批量插入图片的插件&#xff0c;欢迎大家下载&#xff0c;免费试用。 这是图片的文件夹&#xff1a; 主要功能如下: 1&#xff0c;匹配单元格名称的多张图批量插入到一个单元格 该功能支持设置图…

机器学习的入门指南

机器学习的入门指南 机器学习&#xff08;Machine Learning, ML&#xff09;是人工智能&#xff08;AI&#xff09;领域中的一项核心技术&#xff0c;致力于通过数据和算法使计算机具备从经验中学习的能力。在当今的科技世界&#xff0c;机器学习被广泛应用于图像识别、语音识…

一个线性筛的多功能组合:筛法求质数+约数个数+约数和

F:\BC\2024\9>main1 活动代码页: 936 2 2X24 3 3X26 3X39 4X28 5 5X210 5X315 5X525 6X212 7 7X214 7X321 7X535 7X749 8X216 9X218 9X327 10X220 11 11X222 11X333 11X555 11X777 11X11121 12X224 13 13X226 13X339 13X565 13X791 13X11143 13X13169…

腾讯百度阿里华为常见算法面试题TOP100(4):双指针、哈希、滑动窗口

之前总结过字节跳动TOP50算法面试题&#xff1a; 字节跳动常见算法面试题top50整理_沉迷单车的追风少年-CSDN博客_字节算法面试题 目录 双指针 42.接雨水 283.移动零 11.盛最多水的容器 15.三数之和 哈希 1. 两数之和 49.字母异位词分组 128.最长连续序列 滑动窗…

人工智能与机器学习原理精解【20】

文章目录 KNN&#xff08;K-Nearest Neighbor&#xff0c;K最近邻&#xff09;算法概述1. 定义2. 性质3. 计算过程4. 例子和例题5. Julia实现 KNN算法的详细过程算法例子手动实现KNN算法使用现有库实现KNN 参考文献 KNN&#xff08;K-Nearest Neighbor&#xff0c;K最近邻&…

网络协议全景:Linux环境下的TCP/IP、UDP

目录 1.UDP协议解析1.1.定义1.2.UDP报头1.3.特点1.4.缓冲区 2.TCP协议解析2.1.定义2.2.报头解析2.2.1.首部长度&#xff08;4位&#xff09;2.2.2.窗口大小2.2.3.确认应答机制2.2.4.6个标志位 2.3.超时重传机制2.4.三次握手四次挥手2.4.1.全/半连接队列2.4.2.listen2.4.3.TIME_…

代码随想录算法训练营第三十二天 | 509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯

第三十二天打卡&#xff0c;动态规范第一天&#xff01;今天比较简单&#xff0c;主要理解dp的概念 509.斐波那契数列 题目链接 解题过程 状态转移方程 dp[i] dp[i - 1] dp[i - 2]; 动态规划 class Solution { public:int fib(int n) {if (n < 2) return n;int dp[n …

SQL进阶的技巧:如何实现某列的累计乘积?

目录 0 场景描述 1 数据准备 2 问题分析 3 完全情况查询 4 小结 0 场景描述 在做数据处理的时候,尤其是复利累积的时候,有时候会有这样一场景,通过某种条件找到一列数据[X1,X2,X3...Xn],然后想要求y=X1X2X3...Xn。下面给出一个具体案例来详细解释这一问题,如下图所示…

学成在线练习(HTML+CSS)

准备工作 项目目录 内部包含当前网站的所有素材&#xff0c;包含 HTML、CSS、图片、JavaScript等等 1.由于元素具有一些默认样式&#xff0c;可能是我们写网页过程中根本不需要的&#xff0c;所有我们可以在写代码之前就将其清除 base.css /* 基础公共样式&#xff1a;清除…

大模型入门3:理解LLAMA

LLama在transformers库中的代码&#xff0c;以及各部分原理Llama3.1技术报告LLama 33b 微调尝试 Model a stack of DecoderBlocks(SelfAttention, FeedForward, and RMSNorm) decoder block 整体结构&#xff1a;最大的区别在pre-norm x -> norm(x) -> attention() -…

什么是上拉,下拉?

上拉就是将引脚通过一个电阻连接到电源&#xff0c;作用&#xff1a;1.使IO口的不确定电平稳定在高点平&#xff0c;2、为了增加IO口拉电流的能力。 下拉就是将引脚通过一个电阻与GND相连&#xff0c;作用&#xff1a;1.从器件输出电流 2.当IO口为输入状态时&#xff0c;引脚的…

【爱给网-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

Flet全平台开发:软件开发界勇士为Python语言补短板的一次极具挑战性的尝试、冲刺和华丽亮相

一、Flet创始人和开发者介绍、开发Flet的背景介绍 Flet 的创始人和开发者 Feodor Fitsner 是俄罗斯人&#xff0c;就职于微软。 Flet 的第一个版本于 2022 年 6 月发布。这是一个相对较新的库&#xff0c;它基于 Flutter 框架&#xff0c;首先支持的是用 Python 语言开发软件…

速通汇编(五)认识段地址与偏移地址,CS、IP寄存器和jmp指令,DS寄存器

一&#xff0c;地址的概念 通常所说的地址指的是某内存单元在整个机器内存中的物理地址&#xff0c;把整个机器内存比作一个酒店&#xff0c;内存单元就是这个酒店的各个房间&#xff0c;给这些房间编的门牌号&#xff0c;类比回来就是内存单元的物理地址 在第一篇介绍debug的…

文心智能体应用:美国旅游助手的诞生

创造灵感 在如今的数字化时代&#xff0c;旅行体验越来越依赖于智能技术的辅助。从机票预订到行程安排&#xff0c;再到当地美食推荐&#xff0c;智能助手在旅行中的作用愈发重要。尤其在美国这样一个广袤且多样化的国家&#xff0c;拥有一个智能旅行助手能够极大地提升游客的…

C++3D迷宫

目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 #include <iostream> using namespace std; void printmaze(char strmaze[5][5][5]) {cout << "-----" << endl;int i 0;int ia 0…