[LeetCode] 2045. 到达目的地的第二短时间
一、摘要
本文介绍了一种使用BFS求无向图中第二短的距离的算法,本文算法参考自Python3 BFS找出第二短路径。通过使用BFS求出题目中给出的路径图(无向联通图)从节点1到节点n的第二短的路径,再根据路径长度计算出需要耗费的时间。其实在LeetCode官网本题目的题解栏目下已经有很多优秀的题解了,本文除了是使用C++与其他题解有些许不同外无任何优势。还是建议读者阅读其他高赞题解。
二、题解
由于给给节点上红灯、绿灯的亮暗是一致的,因此将各节点间的边长视作1,只要求出从节点0到节点n-1经过的路径长度即可得到总的耗费时间。
因此本题就变成了求节点0到节点n-1的第二短的长度。
需要注意的是,我们要求的是绝对的第二短的路径,如果有两条最短的不同路径长度都为x,那么我还需要继续求得一个大于x的第二短路径。既然是等边长图中,求最短路径我们可以使用BFS。
使用一个队列queue<pair<int, int>>记录所搜到的节点id和从节点0到该节点id的耗时。
为了求第二短的距离因此我们是用两个数组vector<int> first和vector<int> second分别记录节点0到节点id的第一、二短耗时(初始时都设为最大值,在C++中即为INT_MAX)。
在使用队列进行bfs算法时:
- 如果下一个可能要入队列的
节点n_id需要的耗时n_time小于first[n_id],那么说明节点0到节点n_id的最短耗时为n_time,需要入队pair<int,int>(n_id, n_time)``。 - 如果下一个可能要入队列的
节点n_id需要的耗时n_time等于first[n_id],那么说明存在重复的 从节点0到节点n_id的耗时相同、但路径不同 的最短耗时,此时不需要入队; - 如果下一个可能要入队列的
节点n_id需要的耗时n_time大于first[n_id],且小于second[n_id],那么说明节点0到节点n_id的第二短耗时为n_time,需要入队pair<int, int>(n_id, n_time)。 - 如果下一个可能要入队列的
节点n_id需要的耗时n_time大于等于second[n_id],那么说明存在重复的 从节点0到节点n_id的耗时相同、但路径不同 的第二短耗时、或者这是第三短的耗时,此时不需要入队; 
代码如下:
class Solution {
public:
    // 图的节点
    struct Node{
        int idx;    // 节点id
        vector<int> neighbor;   // 相邻的节点id
        Node(int i):idx(i){}
    };
    // 根据此时的时间now计算经过一条边,到达下一个节点的时间
    int getNextTime(int now, int time, int change){
        if((now/change)%2==0){
            now += time;
        }else{
            now += (change - now%change)+time;
        }
        return now;
    }
    int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
        nodes_.resize(n);
        for(int i=0; i<n; i++){
            nodes_[i] = new Node(i);
        }
        // 建图
        for(int i=0; i<edges.size(); i++){
            int a = edges[i][0] - 1;
            int b = edges[i][1] - 1;
            nodes_[a]->neighbor.push_back(b);
            nodes_[b]->neighbor.push_back(a);
        }
        queue<pair<int, int>> que;
        vector<int> first(n, INT_MAX);  // first记录到达节点i最短的耗时
        vector<int> second(n, INT_MAX); // second记录到达节点i第二短的耗时
        que.push(pair<int, int>(0,0));  // 将(0,0)入队,表示达到节点0的耗时为0
        while(que.empty()==false){
            int id = que.front().first;
            int now = que.front().second;
            que.pop();
            for(int i=0; i<nodes_[id]->neighbor.size(); i++){
                int n_id = nodes_[id]->neighbor[i];
                int n_time = getNextTime(now, time, change);
                if(n_id==n-1){   // 如果是第n个节点
                    if(first[n_id]==INT_MAX){    // 第一次到达节点n-1,更新first,且pair<int,int>(n_id,n_time)入队
                        first[n_id] = n_time;
                        que.push(pair<int, int>(n_id, n_time));
                    }else if(n_time>first[n_id] && second[n_id]==INT_MAX){  // 到达节点n-1的第二短距离,返回答案
                        second[n_id] = n_time;
                        return n_time;
                    }
                }else{
                    if(first[n_id]==INT_MAX){   // 第一次到达节点n_id,更新first,且pair<int,int>(n_id,n_time)入队
                        first[n_id] = n_time;
                        que.push(pair<int, int>(n_id, n_time));
                    }else if(n_time>first[n_id] && second[n_id]==INT_MAX){  // 到达节点n-1的第二短的距离,更新second,且pair<int,int>(n_id,n_time)入队
                        second[n_id] = n_time;
                        que.push(pair<int, int>(n_id, n_time));
                    }
                }
            }
        }
        return 0;
    }
    vector<Node*> nodes_;
};
复杂度分析:
- 时间复杂度:O(n+m)
 - 空间复杂度:O(n+m)
其中n为节点个数,m为边个数 
[LeetCode] 2045. 到达目的地的第二短时间的更多相关文章
- 构造定律(constructal law)-构造定律作为第二个时间箭头,将和热力学第二定律一道将宇宙推向无序。
		
优化系统结构,使信息和物质流在结构内的流动更畅通. 构造定律(constructal law) 由Adrian Bejan于1995创立的构造定律(constructal law): For a ...
 - Leetcode春季打卡活动 第二题:206. 反转链表
		
Leetcode春季打卡活动 第二题:206. 反转链表 206. 反转链表 Talk is cheap . Show me the code . /** * Definition for singl ...
 - 广搜最短路(最短时间到达目的地),POJ(3669)
		
题目链接:http://poj.org/problem?id=3669 解题报告: 1.流星坠落的点,四周和自己本身都被毁灭,不断更新每个点被毁灭的时候的最短时间. 2.搜索终点是,到达某个点,这个不 ...
 - [LeetCode] Next Closest Time 下一个最近时间点
		
Given a time represented in the format "HH:MM", form the next closest time by reusing the ...
 - 动态规划之DP中判断是否到达某一状态(最短时间是什么)?
		
codevs1684 垃圾陷阱 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 卡门——农夫约翰极其珍视的一条Holste ...
 - [LeetCode] Employee Free Time 职员的空闲时间
		
We are given a list schedule of employees, which represents the working time for each employee. Each ...
 - LeetCode 176. Second Highest Salary (第二高的薪水)
		
题目标签: 题目给了我们一个工资表,让我们返回第二高的工资. 利用Max,把第一高的工资找到,然后利用 NOT IN,去找到第二高的工资. Java Solution: Runtime: 153ms ...
 - leetcode.1266访问所有点的最小时间
		
平面上有 n 个点,点的位置用整数坐标表示 points[i] = [xi, yi].请你计算访问所有这些点需要的最小时间(以秒为单位). 你可以按照下面的规则在平面上移动: 每一秒沿水平或者竖直方向 ...
 - Java实现 LeetCode 754 到达终点数字(暴力+反向)
		
754. 到达终点数字 在一根无限长的数轴上,你站在0的位置.终点在target的位置. 每次你可以选择向左或向右移动.第 n 次移动(从 1 开始),可以走 n 步. 返回到达终点需要的最小移动次数 ...
 - 第二章 时间控件(DateTime Picker)
		
这家伙太懒了,碰到问题才写博文,嘿嘿. 好了进入正题,二话不说,先放地址: 中文:http://www.bootcss.com/p/bootstrap-datetimepicker/index.htm ...
 
随机推荐
- Linux-ln命令创建链接(软连接/硬链接)
			
1.ln命令介绍 ln命令可以看作是 link 的缩写,其功能是创建文件间的链接,链接类型包括硬链接(hard link)和软链接(符号链接,symbolic link) 2.ln命令格式 ln 命令 ...
 - Python-字符串format方法指定参数
			
一.字符串的format方法有几种指定参数的方式:(1)按照位置传参(默认方式),传入的参数与{}一一对应(2)关键字传参,关键字(keyword)传递是根据每个参数的名字传递参数.关键字并不用遵守位 ...
 - 开源.NetCore通用工具库Xmtool使用连载 - OSS文件上传篇
			
[Github源码] <上一篇> 介绍了Xmtool工具库中的图像处理类库,今天我们继续为大家介绍其中的OSS文件上传类库. 将本地文件上传到服务器是软件系统经常会遇到的需求,例如:设置用 ...
 - JS Leetcode 80. 删除有序数组中的重复项 II题解,常规解法与快慢双指针做法
			
壹 ❀ 引 今天的题目来自LeetCode80. 删除有序数组中的重复项 II,是一道难度中等,但实际挺简单的一道题,题目描述如下: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每 ...
 - SavedStateHandle的介绍----ViewModel不具备保存状态数据的功能
			
LiveData本身不能在进程销毁中存活,当内存不足时,Activity被系统杀死,ViewModel本身也会被销毁. 为了保存LiveData的数据,使用SavedStateHandle. 事故场景 ...
 - Amlogic电视盒子红外遥控适配笔记
			
前一阵做了个安卓6的固件, 在R3300L和Q7上跑的, 其他问题没有, 但是有用户反映原来的遥控器用不了了, 于是检查了一下遥控器配置, 顺便学习一下此类设备的红外遥控机制. 为了方便测试还上淘宝买 ...
 - 【Unity3D】碰撞体组件Collider
			
1 前言  Unity3D 中碰撞体(Collider)组件用于检测运动的物体之间是否发生碰撞,也可以作为触发器使用.产生碰撞的条件是: 2 个游戏对象都有 Collider 至少有一个游戏对象有 ...
 - Set与WeakSet
			
Set与WeakSet Set对象允许存储任何类型的唯一值,无论是原始值或者是对象引用,Set对象中的值不会重复. WeakSet对象允许存储对象弱引用的唯一值,WeakSet对象中的值同样不会重复, ...
 - 阿里面试:Java开发中,应如何避免OOM
			
Java内存管理:避免OOM的10个实用小技巧 引言 在Java开发中,OutOfMemoryError(OOM)错误一直是令开发者头疼的问题,也是Java面试中出现核心频率很高的问题. 那么我们究竟 ...
 - EXPLAIN命令
			
EXPLAIN命令 除了以SELECT开头的查询语句,其余的DELETE.INSERT.REPLACE以及UPDATE语句前边都可以加上EXPLAIN这个词儿,用来查看这些语句的执行计划 Ty ...