博客
关于我
【Lintcode】291. Second Diameter
阅读量:188 次
发布时间:2019-02-28

本文共 3196 字,大约阅读时间需要 10 分钟。

题目地址:

给定一棵树型的无向带权图,求其次大直径(即所有两点距离 d ( v 1 , v 2 ) d(v_1,v_2) d(v1,v2)里第二大的,相等的距离也要参与计数)。

先求最大直径(第一直径)的两个端点 v 1 v_1 v1 v 2 v_2 v2,则 max ⁡ u ≠ v 2 d ( v 1 , u ) \max_{u\ne v_2} d(v_1, u) maxu=v2d(v1,u) max ⁡ u ≠ v 1 d ( v 2 , u ) \max_{u\ne v_1} d(v_2, u) maxu=v1d(v2,u)的最大值即为所求。而求最远点距离可以用BFS来做(主要是为了防止DFS爆栈)。

算法正确性证明:

首先,参考可知从任意点出发找到的最远距离的点一定是直径的一个端点,那么第二直径一定有某个点不是 v 1 v_1 v1或者 v 2 v_2 v2,但是第二直径的非第一直径的端点的那个端点出发,最远距离一定是到达了直径的某个端点的,换言之,第二直径可以从第一直径的某个端点出发,搜到最远的非 v 1 v_1 v1或者 v 2 v_2 v2的点的距离,就是第二直径长度。

代码如下:

import java.util.*;public class Solution {           private long res;        /**     * @param edge: edge[i][0] [1] [2]  start point,end point,value     * @return: return the second diameter length of the tree     */    public long getSecondDiameter(int[][] edge) {           // write your code here        // 顶点数是边数加1        int n = edge.length + 1;        Map
> graph = buildGraph(edge); // 先找到直径的两个端点 int far1 = bfs(0, graph, -1, new boolean[n]); int far2 = bfs(far1, graph, -1, new boolean[n]); // 然后分别从两个端点出发,计算除去另一个端点的情况下的最远距离 bfs(far1, graph, far2, new boolean[n]); bfs(far2, graph, far1, new boolean[n]); return res; } // 返回与v离得最远的,但不是u的点的编号。同时当u不是直径端点的时候,更新res private int bfs(int v, Map
> graph, int u, boolean[] visited) { Queue
queue = new LinkedList<>(); queue.offer(new long[]{ v, 0}); visited[v] = true; // farV存离v最远的点(可能要排除u) int farV = v; // 存v离farV的距离 long farDis = 0; while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { long[] cur = queue.poll(); int nextV = (int) cur[0]; if (graph.containsKey(nextV)) { for (int[] next : graph.get(nextV)) { // 忽略掉第一直径的端点 if (next[0] != u && !visited[next[0]]) { // 为了找到离v最远的点,如果找到更远距离了,则更新距离和遇到的点 if (next[1] + cur[1] > farDis) { farDis = next[1] + cur[1]; farV = next[0]; } visited[next[0]] = true; queue.offer(new long[]{ next[0], next[1] + cur[1]}); } } } } } // 只有其中一个点不是第一直径的时候,才能更新答案 if (u != -1) { res = Math.max(res, farDis); } return farV; } // 邻接表建图,value的[0]存的是与key连接的顶点编号,[1]存的是边长 private Map
> buildGraph(int[][] edges) { Map
> graph = new HashMap<>(); for (int[] edge : edges) { graph.putIfAbsent(edge[0], new ArrayList<>()); graph.get(edge[0]).add(new int[]{ edge[1], edge[2]}); graph.putIfAbsent(edge[1], new ArrayList<>()); graph.get(edge[1]).add(new int[]{ edge[0], edge[2]}); } return graph; }}

时空复杂度 O ( n ) O(n) O(n) n n n是树的顶点个数。

转载地址:http://adjs.baihongyu.com/

你可能感兴趣的文章
nginx:/usr/src/fastdfs-nginx-module/src/common.c:21:25:致命错误:fdfs_define.h:没有那个文件或目录 #include
查看>>
Nginx:NginxConfig可视化配置工具安装
查看>>
Nginx:现代Web服务器的瑞士军刀 | 文章末尾送典藏书籍
查看>>
ngModelController
查看>>
ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
查看>>
ngrok内网穿透可以实现资源共享吗?快解析更加简洁
查看>>
ngrok内网穿透可以实现资源共享吗?快解析更加简洁
查看>>
NHibernate动态添加表
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
Nhibernate的第一个实例
查看>>
NHibernate示例
查看>>
nid修改oracle11gR2数据库名
查看>>
NIFI1.21.0/NIFI1.22.0/NIFI1.24.0/NIFI1.26.0_2024-06-11最新版本安装_采用HTTP方式_搭建集群_实际操作---大数据之Nifi工作笔记0050
查看>>
NIFI1.21.0_java.net.SocketException:_Too many open files 打开的文件太多_实际操作---大数据之Nifi工作笔记0051
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_插入时如果目标表中已存在该数据则自动改为更新数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0058
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_更新时如果目标表中不存在记录就改为插入数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0059
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0_Postgresql和Mysql同时指定库_指定多表_全量同步到Mysql数据库以及Hbase数据库中---大数据之Nifi工作笔记0060
查看>>