力扣题解815

news2024/9/20 2:42:26

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

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

题目描述(困难)​:

公交路线

给你一个数组 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.coloradmin.cn/o/2143187.html

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

相关文章

红黑树的插入(NGINX源码)

下载并查看NGINX源码 访问NGINX下载页面&#xff0c;找到所需版本 https://nginx.org/en/download.html 使用wget下载源码包&#xff0c;替换版本号为所需版本 wget http://nginx.org/download/nginx-1.24.0.tar.gz解压源码包 tar -xzvf nginx-1.24.0.tar.gz进入解压后的目…

Java的输入输出

秋招笔试很多都是要自己写输出输出的&#xff0c;所以对常见的整理一下&#xff0c;后续也会持续更新的~~~ 目录 1.java中的Scanner类 1.1next()方法和nextLine()方法的区别 1. next() 方法 示例 2. nextLine() 方法 示例 主要区别 使用场景 2.print类 3.常用的转换…

音频左右声道数据传输_2024年9月6日

如下为音频数据传输标准I2S总线的基本时序图 I2S slave将I2S master发送来的左右声道的串行数据DATA转变为16bit的并行数据 WS为左右声道选择信号&#xff0c;WS高代表左声道&#xff0c;WS低代表右声道; WS为高和为低都持续18个周期&#xff0c;前面16个周期用来传输数据。 I2…

npm安装时候报错certificate has expired

打开了一个很久没用的电脑&#xff0c;npm和node都装好了&#xff0c;安装包的时候一直报错 request to https://registry.npm.taobao.org/create-react-app failed, reason: certificate has expired而且先报错rollbackFailedOptional 然而npm没什么问题&#xff0c;是ssl过…

【数据结构与算法 | 灵神题单 | 自底向上DFS篇】力扣965, 2331, 100, 1379

1. 力扣965&#xff1a;单值二叉树 1.1 题目&#xff1a; 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。 只有给定的树是单值二叉树时&#xff0c;才返回 true&#xff1b;否则返回 false。 示例 1&#xff1a; 输入&#xff1a;[1,1,1,1,1,n…

UE5学习笔记22-武器瞄准和武器自动开火

0、一些疑问的记录 1.UUserWidget类和AHUD类的区别。两者都是关于界面显示的类。 实践&#xff1a; 想让界面和用户有交互使用UUserWidget&#xff0c;如果不要交互只是显示使用AHUD类&#xff0c;例如使用UUserWidget类制作开始界面&#xff0c;游戏开始&#xff0c;游戏设置&…

TensorRT-LLM——优化大型语言模型推理以实现最大性能的综合指南

引言 随着对大型语言模型 (LLM) 的需求不断增长&#xff0c;确保快速、高效和可扩展的推理变得比以往任何时候都更加重要。NVIDIA 的 TensorRT-LLM 通过提供一套专为 LLM 推理设计的强大工具和优化&#xff0c;TensorRT-LLM 可以应对这一挑战。TensorRT-LLM 提供了一系列令人印…

AD的入门操作

锦囊 1、打开AD后&#xff0c;一般默认打开上一个工程&#xff0c;这个时候如果想要打开新的工程&#xff0c;那就必须要创建一个项目&#xff0c;然后再在项目中添加原理图库和PCB库。 2、大多数情况下&#xff0c;直接使用库&#xff0c;不用自己再画原理图和封装库。 3、…

LeetCode[中等] 49.字母异位词分组

给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 思路&#xff1a; new Dictionary<string, List<string>>() 存储数据&#xff0c;key为排序之后的字符…

超高速传输 -- 相干光通信和非相干光通信

概述&#xff1a;技术对比 项目非相干光通信相干通信定义不需要相干本振光的光传输系统。采用本振光进行相干检测的光传输系统。调制解调技术发送端&#xff1a;强度调制。 接收端&#xff1a;直接检测。发送端&#xff1a;外调制。 接收端&#xff1a;本振光相干检测。码型幅…

完美的宝塔面板防御策略,基于 fail2ban

之前分享过宝塔面板配合fail2ban&#xff0c;以及开启cloudflare的cdn双重防御的教程&#xff0c;并制作了便捷的脚本这次不靠cloudflare的减速cdn&#xff0c;看看防御效果怎么样 系统环境 debian/ubuntu nginx 宝塔面板 注意要点 1.在宝塔面板开启站点日志 2.添加服务器白名…

加密与安全_HTTPS TLS 1.2 连接(RSA 握手)的整个过程解读

文章目录 HTTPS 数据传输的安全性保障SSL/TLS 作为混合加密系统的典范HTTPS TLS 1.2 连接&#xff08;RSA 握手&#xff09;的整个过程TLS 握手过程解析1. TCP 三次握手 (最顶部的黄色部分)2. TLS 握手阶段 (红色部分)2.1 Client Hello2.2 Server Hello2.3 CA 证书验证2.4 Clie…

[Python数据可视化]Plotly Express: 地图数据可视化的魅力

在数据分析和可视化的世界中&#xff0c;地图数据可视化是一个强大而直观的工具&#xff0c;它可以帮助我们更好地理解和解释地理数据。Python 的 Plotly Express 库提供了一个简单而强大的方式来创建各种地图。本文将通过一个简单的示例&#xff0c;展示如何使用 Plotly Expre…

【JavaWeb】利用IDEA2024+tomcat10配置web6.0版本搭建JavaWeb开发项目

之前写过一篇文章&#xff1a;《【JavaWeb】利用IntelliJ IDEA 2024.1.4 Tomcat10 搭建Java Web项目开发环境&#xff08;图文超详细&#xff09;》详细讲解了如何搭建JavaWeb项目的开发环境&#xff0c;里面默认使用的Web版本是4.0版本的。但在某些时候tomcat10可能无法运行we…

24年蓝桥杯及攻防世界赛题-MISC-1

2 What-is-this AZADI TOWER 3 Avatar 题目 一个恐怖份子上传了这张照片到社交网络。里面藏了什么信息&#xff1f;隐藏内容即flag 解题 ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/outguess] └─$ outguess -r 035bfaa85410429495786d8ea6ecd296.jpg flag1.txt Rea…

iKuai使用及设置流程

iKuai使用及设置流程 iKuai安装步骤 一、配置主机 1.电脑连接ETH0网口 2.ETH1网口连接猫上面的千兆口 3.手动配置pc的IP地址和192.168.1.1./24在同一网段 3.浏览器输入192.168.1.1 admin admin 二、外网设置 1.直接联通电信网络设置 2.点击 网络设置-内外网设置-点击接…

LeetCode从入门到超凡(一)枚举算法

前言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的LeetCode学习总结文档&#xff1b;本文主要讲解枚举算法。&#x1f495;&#x1f495;&#x1f60a; 一、基本概念 1.定义 定义&am…

记录小数点

记录data frame小数点后面省略掉0的问题 iloc得到的series .to_list() 0被省略掉 to_list() 可能会将浮点数转换为默认格式。先将数据转换为字符串以保留格式 df_2708.iloc[2,:].apply(lambda x: f{x:.3f}).to_list()自定义保留小数点后几位 def formatter(value):return &q…

【工作流集成】springboot+vue工作流审批系统(实际源码)

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;一套完整并且实际运用在多套项目中的案例&#xff0c;满足日常业务流程审批需求。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端…

Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 垃圾回收算法

文章目录 垃圾回收机制垃圾判断算法引用计数法可达性分析算法虚拟机栈中的引用&#xff08;方法的参数、局部变量等&#xff09;本地方法栈中 JNI 的引用类静态变量运行时常量池中的常量 垃圾收集算法Mark-Sweep&#xff08;标记-清除&#xff09;算法Copying&#xff08;标记-…