力扣刷题之815.公交路线

题干描述

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

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

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

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

示例 1:

输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6
输出:2
解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。 

示例 2:

输入:routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12
输出:-1

题干分析

问题描述

       已知我们有这一系列的公交线路,以及routes数组,其中routes[i]表示dii来你个公交所进过的车站列表。每辆公交车按照起路线循环行驶。

  • 目标:从起始站点source出发,前往目标站点target,且进通过乘坐公交车。
  • 要求:找到从source到target需要乘坐的最少公交车数量。
  • 注意:如果无法到达目标站点,返回-1。

 示例:

1.

输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6
输出:2
解释:乘坐公交车 0 从站点 1 到站点 7,然后换乘公交车 1 到站点 6。

 2.

输入:routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12
输出:-1
解释:无法从站点 15 到达站点 12。

解题思路

        这个问题可以抽象为图的最短路径问题。我们需要构建一个公交车之间的图,然后使用官渡有限搜索(BFS)来找到从起始站点到目标站的最短路径。

  • 节点(顶点):公交车(每辆公交车做一个节点)。
  • 边(连接):若两辆公交车之间存在公共的站点,则它们之间可以换乘,形成一条边。
  • 起始节点:所有进过source站点的公交车。
  • 目标节点:所有经过target站点的公交车。
  • 权重:每次换乘所一步,所以没条边的权重为1。

 这里我们以示例2为例,大概如下:

 步骤概述

1.建立站点到公交车的映射:
  • 为每个站点创建一个列表,记录经过agic站点的所有公交车。
2.构建公交车之间的连接
  • 对于没对公交车,如果它们有公共的站点,则它们之间可以直接换乘。
3.使用BFS进行搜索:
  • 从所有经过source站点的公交车开始搜索。
  • 逐层遍历可以换乘的公交车,记录乘坐的公交车数量。
  • 如果某一辆公交车经过target站点,则返回已乘坐的公交车数量。
4.处理无法到达的情况:
  • 如果在搜索结束后,仍未找到经过target站点的公交车,则返回-1。

代码讲解 

#define MAX_BUS_STOPS 1000000
#define MAX_BUSES 500typedef struct {int bus_id;int next;
} BusNode;typedef struct {int head;
} BusStop;typedef struct {int bus_id;int depth;
} QueueNode;
第一步:定义数据结构
定义结构体BusNode:用于存储经过某个站点的公交车的链表节点,其中:
  • bus_id:用于定义公交车的编号。
  • next:用于指向下一个BusNode的索引。
定义结构体BusStop:表示一个公交站点,其中:
  • head:指向该站点对应的公交车链表的头节点索引。
定义结构体QueueNode:用于BFS队列,表示一个代访问的公交车节点。
  • bus_id:公交车的编号。
  • depth:到达该公交车所需乘坐的公交车数量。
第二步 特殊情况考虑
  • 如果source等于target,则无需乘坐公交车,直接返回0。
int numBusesToDestination(int** routes, int routesSize, int* routesColSize, int source, int target) {if (source == target) return 0;
 第三步 初始化站点到公交车的映射
  • 创建一个大小为 MAX_BUS_STOPS 的数组 busStops,用于存储每个站点对应的公交车链表。
  • 初始化每个站点的 head-1,表示链表为空。
    // 创建站点到公交车的映射BusStop* busStops = (BusStop*)malloc(sizeof(BusStop) * MAX_BUS_STOPS);for (int i = 0; i < MAX_BUS_STOPS; i++) {busStops[i].head = -1;}
 第四步  初始化公交车链表数组
  • 创建一个数组busNodes,用于存储所有的BusNode节点
  • busNodeCount用于记录已经使用的节点数量。     
    for (int bus_id = 0; bus_id < routesSize; bus_id++) {for (int j = 0; j < routesColSize[bus_id]; j++) {int bus_stop_id = routes[bus_id][j];BusNode* node = &busNodes[busNodeCount++];node->bus_id = bus_id;node->next = busStops[bus_stop_id].head;busStops[bus_stop_id].head = busNodeCount - 1;}}
 第五步 建立站点到公交车的映射
  • 遍历没来那个公交车的路线,将公交车编号添加到经过的每个站点的链表中。
  • 对于每个站点,新的BusNode节点插入到链表头部。实现了链表的建立。
    // BFS 初始化int visitedBuses[MAX_BUSES];memset(visitedBuses, 0, sizeof(visitedBuses));int queueSize = MAX_BUSES * 1000;QueueNode* queue = (QueueNode*)malloc(sizeof(QueueNode) * queueSize);int front = 0, rear = 0;
第六步 初始化 BFS所需的数据结构:
  • visiteBuses:记录已经访问过的公交车,防止重复访问。
  • queue:BFS队列,用于存储代访问的公交车。
  • front和rear:队列的头尾指针。
    // 将经过起始站点的公交车加入队列for (int idx = busStops[source].head; idx != -1; idx = busNodes[idx].next) {int bus_id = busNodes[idx].bus_id;if (!visitedBuses[bus_id]) {visitedBuses[bus_id] = 1;queue[rear++] = (QueueNode){bus_id, 1};}}
 第七步 将经过source站点的公交车加入队列
  • 遍历source站点的公交车链表,将每个公交车编号加入队列,初始乘坐公交车数量为1。
  • 标记这些公交车为已访问。
    // BFS 遍历while (front < rear) {QueueNode current = queue[front++];int bus_id = current.bus_id;int depth = current.depth;// 检查该公交车是否经过目标站点for (int i = 0; i < routesColSize[bus_id]; i++) {int bus_stop_id = routes[bus_id][i];if (bus_stop_id == target) {free(busStops);free(busNodes);free(queue);return depth;}}
第八步 开始BFS遍历

        从队列中取出一个公交车节点,湖区当前公交车编号和已乘坐的公交车数量。检查当前公交车是否经过target站点:

  • 遍历该公交车的路线,如果发现target站点,返回当前乘坐的公交车数量depth。
 第九步 遍历当前公交车经过的所有站点
        // 将该公交车经过的所有站点的其他公交车加入队列for (int i = 0; i < routesColSize[bus_id]; i++) {int bus_stop_id = routes[bus_id][i];for (int idx = busStops[bus_stop_id].head; idx != -1; idx = busNodes[idx].next) {int next_bus_id = busNodes[idx].bus_id;if (!visitedBuses[next_bus_id]) {visitedBuses[next_bus_id] = 1;queue[rear++] = (QueueNode){next_bus_id, depth + 1};}}}}

对于当前公交车经过的每个站点

  • 获取经过该站点的所有公交车。
  • 如果这些公交未被访问过,将其加入队列,乘坐的公交车数量+1。
  • 标记这些公交车为已访问
第十步 无法到达目标站点:
  • 如果队列为空,仍未找到经过target站点的公交车,释放动态分配的内存,返回-1.

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

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

相关文章

全国职业院校技能大赛(大数据赛项)-平台搭建Spark、Scala笔记

Spark作为一个开源的分布式计算框架拥有高效的数据处理能力、丰富的生态系统、多语言支持以及广泛的行业应用。Scala是一种静态类型的编程语言&#xff0c;它结合了面向对象编程和函数式编程的特性&#xff0c;被誉为通用的“大数据语言”。而二者的结合更能迸发出新奇的化学反…

Dify创建自定义工具,调用ASP.NET Core WebAPI时的注意事项(出现错误:Reached maximum retries (3) for URL ...)

1、要配置Swagger using Microsoft.AspNetCore.Mvc; using Microsoft.OpenApi.Models;var builder WebApplication.CreateBuilder(args);builder.Services.AddCors(options > {options.AddPolicy("AllowSpecificOrigin",builder > builder.WithOrigins("…

Transformers | 在自己的电脑上开启预训练大模型使用之旅!

本文内容主要包括两部分&#xff1a; Hugging Face 社区介绍 如何使用 Transformers 库的模型 1. Hugging Face 社区介绍 Hugging Face (https://huggingface.co/) 是一个 Hub 社区&#xff0c;它和 GitHub 相同的是&#xff0c;他们都是基于 Git 进行版本控制的存储库社区&…

SRS流媒体服务器在宝塔面板下的安装

目录 一、安装 1、安装Docker 2、安装srs 二、测试 1、进入后台 2、推流 3、播放测试: (1)网页 (2)拉流 之前一篇文章,我们介绍了SRS流媒体服务器在CentOS下的安装,安装流程还是比较麻烦且耗时的,其实SRS支持Docker部署,今天我们介绍在宝塔面板的Docker中部署…

【C++篇】~类和对象(中)

类和对象&#xff08;中&#xff09; 1.类的默认成员函数​ 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前…

深入探索PostgreSQL优化器的代价模型(建议收藏)

PawSQL优化引擎的实现深受PostgreSQL优化器的影响&#xff0c;本文我们来揭密PostgreSQL的代价模型。PawSQL专注于数据库性能优化自动化和智能化&#xff0c;提供的解决方案覆盖SQL开发、测试、运维的整个流程&#xff0c;广泛支持MySQL、PostgreSQL、OpenGauss、Oracle等主流商…

数据脱敏-快速使用

1.数据脱敏定义 数据脱敏百度百科中是这样定义的&#xff1a; 数据脱敏&#xff0c;指对某些敏感信息通过脱敏规则进行数据的变形&#xff0c;实现敏感隐私数据的可靠保护。 因为在真正的生产环境中,很多数据是不能直接返回,但是我们工作的时候可能经常性的需要返回一些用户信…

历年大厂校招 网络安全面试题(80+经验贴)

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

为什么要使用多线程

为什么要使用多线程 任务分解&#xff1a;耗时的操作&#xff0c;任务分解&#xff0c;实时响应。数据分解&#xff1a;充分利用多核CPU处理数据。数据流分解&#xff1a;读写分离&#xff0c;解耦合设计。 #include <iostream> #include<thread> using namespac…

【Unity编辑器扩展】解决uGUI动效痛点 零代码可视化快速制作UI动效 DOTween Sequence可视化

UI动效痛点&#xff1a; UI动效一直是Unity游戏开发的一大痛点&#xff0c;大部分项目都在使用Animator/Animation制作UI动效。而Animation是以节点路径记录动画&#xff0c;一旦UI层级、节点名变更就会导致动效返工&#xff0c;且Animation编辑器缓动曲线很难控制&#xff0c…

【论文速看】DL最新进展20240923-长尾综述、人脸防伪、图像分割

目录 【长尾学习】【人脸防伪】【图像分割】 【长尾学习】 [2024综述] A Systematic Review on Long-Tailed Learning 论文链接&#xff1a;https://arxiv.org/pdf/2408.00483 长尾数据是一种特殊类型的多类不平衡数据&#xff0c;其中包含大量少数/尾部类别&#xff0c;这些类…

C:内存函数

目录 前言&#xff1a; 一、memcpy 函数的使用及实现 1、memcpy函数的介绍 1.1 memcpy函数参数解读 2、memcpy函数的使用 3、memcpy函数的模拟实现 二、memmove函数的使用及模拟 1、memmove函数的使用 2、memmove函数的模拟实现 三、memset 函数的使用 1、memset函数的…

PyCharm下载和安装教程

Python、C/C、C#、DSL、Go、Groovy、Java、JavaScript、Objective-C、PHP 等编程语言。 图 1 JetBrains 开发工具 PyCharm下载和安装 进入 PyCharm官方下载页面(如图 2 所示)&#xff0c;可以看到 PyCharm 有 2 个版本&#xff0c;分别是 Professional(专业版)和 Community(社…

Mybatis百万数据插入(含导出)

1 一般一次性插入多条数据 传统的sql语句&#xff1a; INSERT INTO table1 ( field1, field2 ) VALUES( "data1", "data2" ); INSERT INTO table1 ( field1, field2 ) VALUES( "data1", "data2" ); INSERT INTO table1 ( field1, fi…

DirectX修复助手

在日常使用电脑时&#xff0c;我们可能会遇到提示缺少DLL文件&#xff0c;如0xc000007b错误、缺少d3dxxx.dll等问题&#xff0c;这些会影响软件运行甚至导致系统不稳定。以下是一些常见的DLL问题原因和一个修复工具&#xff0c;希望能帮到你。 DLL文件问题的常见原因 软件安装…

20 基于STM32的温度、电流、电压检测proteus仿真系统(OLED、DHT11、继电器、电机)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STM32F103C8T6 采用DHT11读取温度、滑动变阻器模拟读取电流、电压。 通过OLED屏幕显示&#xff0c;设置电流阈值为80&#xff0c;电流小阈值为50&#xff0c;电压阈值为60&#xff0c;温度阈值…

24. Revit API: 几何对象(五)- (Sur)Face

一、前言 虽然Face是GeometryObject的子类&#xff0c;Surface不是&#xff0c;但这两者之间还是挺有关联的&#xff0c;每个Face都有一个对应的Surface&#xff0c;类似于Edge和Curve的关系。 Surface是数学意义上的面&#xff0c;纯定义。 Face是几何形状&#xff08;实体&a…

css如何设置间距

在CSS中设置间距是非常常见的需求&#xff0c;可以通过多种属性来实现。以下是一些常用的CSS属性及其用法&#xff0c;用于设置元素之间的间距&#xff1a; 内边距&#xff08;Padding&#xff09; padding 属性用于设置元素内容与元素边框之间的距离。可以分别设置四个方向的…

视频质量评价SimpleVQA

目录 一、研究意义 例子 二、介绍 三、文章解读 3.1 论文动机 3.2论文思路 3.3方法 3.3.1网络框架 3.3.2公式解读 3.3.3核心创新 3.3.4理解 &#xff01;&#xff01;&#xff01;作者对模型的改进 本人算法框体 3.3.5实验细节&#xff1a; 四、代码复现 4.1代码文件简介 4.2数…

leetcode第二十六题:删去有序数组的重复项

给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k &#xff0c;你…