博客
关于我
【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和Tomcat的区别
查看>>
Nginx在Windows上和Linux上(Docker启动)分别配置基本身份认证示例
查看>>
Nginx在Windows下载安装启动与配置前后端请求代理
查看>>
Nginx在开发中常用的基础命令
查看>>
Nginx多域名,多证书,多服务配置,实用版
查看>>
nginx如何实现图片防盗链
查看>>
Nginx学习总结(11)——提高Nginx服务器的安全性,稳定性和性能的12种技巧
查看>>
Nginx学习总结(12)——Nginx各项配置总结
查看>>
Nginx学习总结(13)——Nginx 重要知识点回顾
查看>>
Nginx学习总结(14)——Nginx配置参数详细说明与整理
查看>>
Nginx学习总结(15)—— 提升 Web 应用性能的十个步骤
查看>>
Nginx学习总结(8)——Nginx服务器详解
查看>>
nginx学习笔记002---Nginx代理配置_案例1_实现了对前端代码的方向代理_并且配置了后端api接口的访问地址
查看>>
nginx学习笔记003---Nginx代理配置_注意,在Windows中路径要用/
查看>>
Nginx学习笔记(一) Nginx架构
查看>>
Nginx安装SSL模块 nginx: the “ssl” parameter requires ngx_http_ssl_module in /usr/local/nginx/conf/nginx
查看>>
nginx安装stream模块配置tcp/udp端口转发
查看>>
nginx安装Stream模块配置tcp/udp端口转发
查看>>
Nginx安装与常见命令
查看>>
nginx安装与配置
查看>>