当前位置: 首页 > news >正文

【Leetcode 每日一题】743. 网络延迟时间

问题背景

n n n 个网络节点,标记为 1 1 1 n n n
给你一个列表 t i m e s times times,表示信号经过 有向 边的传递时间。 t i m e s [ i ] = ( u i , v i , w i ) times[i] = (u_i, v_i, w_i) times[i]=(ui,vi,wi),其中 u i u_i ui 是源节点, v i v_i vi 是目标节点, w i w_i wi 是一个信号从源节点传递到目标节点的时间。
现在,从某个节点 K K K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 − 1 -1 1

数据约束

  • 1 ≤ k ≤ n ≤ 100 1 \le k \le n \le 100 1kn100
  • 1 ≤ t i m e s . l e n g t h ≤ 6000 1 \le times.length \le 6000 1times.length6000
  • t i m e s [ i ] . l e n g t h = 3 times[i].length = 3 times[i].length=3
  • 1 ≤ u i , v i ≤ n 1 \le u_i, v_i \le n 1ui,vin
  • u i ! = v i u_i != v_i ui!=vi
  • 0 ≤ w i ≤ 100 0 \le w_i \le 100 0wi100
  • 所有 ( u i , v i ) (u_i, v_i) (ui,vi) 对都 互不相同(即,不含重复边)

解题过程

单源最短路模板题,所有权重都是正值,无脑 D i j k s t r a Dijkstra Dijkstra,时空复杂度都是 O ( n 2 ) O(n ^ 2) O(n2)

可以用堆来优化流程中查找最短路径的过程,在图是稀疏图的情况下( m ≪ n m \ll n mn)把时间复杂度优化到 O ( m l o g m ) O(mlogm) O(mlogm),空间复杂度为 O ( m ) O(m) O(m),其中 m m m 是数组 t i m s tims tims 的长度,可以看作有向图中边的数量。但如果输入的是稠密图( m ≈ n m \approx n mn),这时候相对而言起主导作用的是 m m m,那么这个方法的复杂度会达到 O ( n 2 l o g m ) O(n ^ 2 logm) O(n2logm),因为堆总是需要 O ( l o g m ) O(logm) O(logm) 量级的时间来调整。

具体实现

朴素邻接矩阵最短路

class Solution {// 一般来说正无穷是用 Integer.MAX_VALUE 的,Dijkstra 中涉及加法会溢出private static final int INF = Integer.MAX_VALUE >>> 1;public int networkDelayTime(int[][] times, int n, int k) {int[][] graph = new int[n][n];// 初始化所有节点之间不可达for(int[] row : graph) {Arrays.fill(row, INF);}// 设置节点之间的权值for(int[] time : times) {graph[time[0] - 1][time[1] - 1] = time[2];}int max = 0;int[] dis = new int[n];Arrays.fill(dis, INF); // 初始化所有节点之间的距离为正无穷dis[k - 1] = 0; // 源节点到自身可达,使得更新过程有初始节点可选中boolean[] visited = new boolean[n]; // 初始化所有节点未访问过while(true) {// 节点编号从 0 开始,初始化为 -1 避免歧义int curIndex = -1;// 找出未访问的距源节点最近的节点for(int i = 0; i < n; i++) {if(!visited[i] && (curIndex < 0 || dis[i] < dis[curIndex])) {curIndex = i;}}// 如果所有节点都被访问过,那么最后一次更新的最短路径长度就是答案,直接返回if(curIndex < 0) {return max;}// 如果有未访问节点不可达,那么根据题目要求返回 -1if(dis[curIndex] == INF) {return -1;}// 更新这一轮的最短路径长度,Dijkstra 贪心的特点决定了这个值会越来越大max = dis[curIndex];visited[curIndex] = true; // 标记已访问过// 更新所有节点的最短路径长度for(int i = 0; i < n; i++) {dis[i] = Math.min(dis[i], dis[curIndex] + graph[curIndex][i]);} }}
}

堆优化邻接表最短路

class Solution {public int networkDelayTime(int[][] times, int n, int k) {// 初始化邻接表List<int[]>[] graph = new ArrayList[n];Arrays.setAll(graph, item -> new ArrayList<>());for(int[] time : times) {graph[time[0] - 1].add(new int[]{time[1] - 1, time[2]});}int max = 0;int remain = n; // 剩余未处理节点个数为 nint[] dis = new int[n];Arrays.fill(dis, Integer.MAX_VALUE); // 初始化所有节点之间的距离为正无穷dis[k - 1] = 0; // 源节点到自身可达,使得更新过程有初始节点可选中// 注意,堆应根据权值来调整PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((i1, i2) -> i1[1] - i2[1]);// 堆中的而元素表示到达节点和最短路径长度,也就是潜在的新路径的所有可能priorityQueue.offer(new int[]{k - 1, 0});while(!priorityQueue.isEmpty()) {int[] top = priorityQueue.poll(); // 最小堆堆顶一定是当前最近的节点int curIndex = top[0];int curDis = top[1];// 同一个节点可能会被重复记录,重复的情况不会影响结果,直接跳过if(curDis > dis[curIndex]) {continue;}// 更新这一轮的最短路径长度,Dijkstra 贪心的特点决定了这个值会越来越大max = curDis;remain--; // 当前节点处理完成,剩余未处理节点个数减少// 根据所有到达节点更新最短路径长度,增强 for 循环处理列表for(int[] row : graph[curIndex]) {int next = row[0];int newDis = curDis + row[1];if(newDis < dis[next]) {dis[next] = newDis;priorityQueue.offer(new int[]{next, newDis});}}}return remain == 0 ? max : -1; // 仍有剩余节点,说明不可达,那么根据题目要求返回 -1}
}

http://www.mrgr.cn/news/78418.html

相关文章:

  • 使用 VLC 在本地搭建流媒体服务器 (详细版)
  • fiddler抓包工具与requests库构建自动化报告
  • 1- 9 C 语言面向对象
  • 软件测试丨Pytest生命周期与数据驱动
  • Spring中实现动态数据源切换,基于AbstractRoutingDataSource
  • 内核模块签名验证
  • 使用ENSP实现NAT
  • PostgreSQL 三种关库模式
  • CTO 实际上是在做什么?
  • LLamafactory API部署与使用异步方式 API 调用优化大模型推理效率
  • 矩阵重新排列——sort函数
  • 使用ENSP实现默认路由
  • 蓝桥杯c++算法秒杀【6】之动态规划【上】(数字三角形、砝码称重(背包问题)、括号序列、组合数问题:::非常典型的必刷例题!!!)
  • 鸿蒙NEXT元服务:利用App Linking实现无缝跳转与二维码拉起
  • 【Leetcode Top 100】48. 旋转图像
  • 微信小程序按字母顺序渲染城市 功能实现详细讲解
  • ThingsBoard规则链节点:GCP Pub/Sub 节点详解
  • 技术文档的规划布局:构建清晰的知识蓝图
  • 【Leetcode 每日一题】632. 最小区间
  • Springboot整合分布式任务调度平台XXL-Job实现定时任务
  • 更优雅的 yolo v11 标注工具 AutoLabel Conda环境直接识别训练
  • PGSQL学习笔记 -- 从入门到放弃
  • 使用Spring Data MongoDB中的MongoTemplate实现分组查询最新的数据
  • 前端应用界面的展示与优化(记录)
  • C++学习日记---第14天(蓝桥杯备赛)
  • 什么是代理,nodenginx前端代理详解