博客
关于我
【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/

你可能感兴趣的文章
nacos自动刷新配置
查看>>
nacos运行报错问题之一
查看>>
Nacos部署中的一些常见问题汇总
查看>>
NACOS部署,微服务框架之NACOS-单机、集群方式部署
查看>>
Nacos配置Mysql数据库
查看>>
Nacos配置中心中配置文件的创建、微服务读取nacos配置中心
查看>>
Nacos配置中心集群原理及源码分析
查看>>
nacos配置在代码中如何引用
查看>>
nacos配置新增不成功
查看>>
nacos配置自动刷新源码解析
查看>>
nacos集成分布式事务插件Seata的序列化问题,实际上是Seata本身存在bug!!
查看>>
Nacos集群搭建
查看>>
nacos集群搭建
查看>>
nacos集群网络分区对的影响和运维方式
查看>>
nacos集群节点故障对应用的影响以及应急方法
查看>>
nacos集群配置详解
查看>>
Nagios 3.0 Jumpstart Guide For Linux – Overview, Installation and Configuration
查看>>
nagios 实时监控 iptables 状态
查看>>
WAP短信格式解析及在Linux下用C语言实现
查看>>
nagios+cacti整合
查看>>