给定一棵多叉树,求出这棵树的直径,即树上最远两点的距离。
包含n个结点,n-1条边的连通图称为树。
示例1的树如下图所示。其中4到5之间的路径最长,是树的直径,距离为5+2+4=11
数据范围:
,保证最终结果满足
要求:空间复杂度:
,时间复杂度
本题需要1个注意的地方:
function solve( n , Tree_edge , Edge_value ) {
let res = 0;
const obj= {};
for (let i=0; i<Tree_edge.length; ++i) {
const v = Tree_edge[i];
const w = Edge_value[i] || 0;
obj[v.start] ? obj[v.start].push([w, v.end]):
obj[v.start] = [[w, v.end]];
obj[v.end] ? obj[v.end].push([w, v.start]):
obj[v.end] = [[w, v.start]];
}
const dfs = (node, pre, w) => {
let i=0;
const arr = [];
while(i<obj[node].length) {
if (obj[node][i][1] !== pre)
arr.push(dfs(obj[node][i][1], node, obj[node][i][0]));
++i;
}
arr.push(0, 0); // 防止没有
const one = Math.max(...arr);
arr[arr.indexOf(one)] = -Infinity;
const two = Math.max(...arr);
if (one + two > res) res = one + two;
return one + w;
};
dfs(Tree_edge[0].start, -1, Edge_value[0]);
return res;
} function solve( n , Tree_edge , Edge_value ) {
const tree = buildTree(n, Tree_edge, Edge_value);
const visited = new Array(n).fill(false);
const {max} = dfs({tree, visited});
return max;
}
function buildTree(n, tree_edge, edge_value) {
const tree = new Array(n).fill(null).map(_ => []);
for (let i = 0; i < tree_edge.length; i++) {
const {start, end} = tree_edge[i];
const edge_val = edge_value[i];
tree[start].push({child: end, len: edge_val});
tree[end].push({child: start, len: edge_val});
}
return tree;
}
function dfs({tree, visited, idx = 0, max = 0}) {
if (tree[idx].length === 0 || visited[idx]) return 0;
visited[idx] = true;
let m1 = 0, m2 = 0;
for (let i = 0; i < tree[idx].length; i++) {
const {child, len} = tree[idx][i];
if (visited[child]) continue;
const res = dfs({tree, visited, idx: child, max: max});
const distance = res.maxDistance + len;
max = res.max;
if (distance >= m1) {
m2 = m1;
m1 = distance;
} else if (distance > m2) {
m2 = distance;
}
}
max = Math.max(max, m1 + m2);
return {maxDistance: m1, max: max};
}
/*
* function Interval(a, b){
* this.start = a || 0;
* this.end = b || 0;
* }
*/
function solve( n , Tree_edge , Edge_value ) {
let nodes = [];//所有节点的数组形式
let toZeroArr = [0];//所有节点到零节点的长度集合
// 0节点到其他节点的长度集合
function to_0_length(){
let node = nodes[0];
let arrayVal = [];//node到其他节点的总长度集合
let j = 1;
while(j < nodes.length){
let end = nodes[j];
let length = 0;//当前节点I的总长度
while(1){
let index;
for(index in Tree_edge){
if(end == Tree_edge[index][1]){
length += Edge_value[index];
end = Tree_edge[index][0];
break;
}
}
if(node == Tree_edge[index][0]){
break;
}
}
arrayVal.push(length)
j++;
}
return arrayVal;
}
//返回共同父亲节点下标
function commonParentNode(node1,node2){
let fnode1 = [node1];
let fnode2 = [node2];
for(let index=0;index< Tree_edge.length;index++){
let item = Tree_edge[index];
if(node1==item[1]){
fnode1.push(item[0])
node1 = item[0];
if(node1==0){
break
}
index = -1;
}
}
for(let index=0;index< Tree_edge.length;index++){
let item = Tree_edge[index];
if(node2==item[1]){
fnode2.push(item[0])
node2 = item[0];
if(node2==0){
break
}
index = -1;
}
}
fnode1 = fnode1.reverse();
fnode2 = fnode2.reverse();
let flag = 0;
let i = 0;
while(i<fnode1.length&&i<fnode2.length){
if(fnode2[i]==fnode1[i]){
flag = i;
}
i++;
}
return flag;
}
function toOtherNodeMaxLength(node,i){//node节点到其他节点的最大长度
let arrayVal = [];//node到其他节点的总长度集合
let j = i+1;
while(j < nodes.length){
let k = commonParentNode(node,nodes[j]);
arrayVal.push(toZeroArr[j]+toZeroArr[i]-2*toZeroArr[k]);
j++;
}
return Math.max(...arrayVal);
}
Tree_edge = Tree_edge.map((item,index)=>{
return [item.start,item.end]
})
//遍历所有节点 统计出各个节点
nodes.push(Tree_edge[0][0])
Tree_edge.map(nodeArr=>{
nodes.push(nodeArr[1])
})
toZeroArr = toZeroArr.concat(to_0_length());
let maxNodesArr = [Math.max(...toZeroArr)];
nodes.map((item,index)=>{
if(index!=0&&index!=nodes.length-1){
maxNodesArr.push(toOtherNodeMaxLength(item,index));
}
})
return Math.max(...maxNodesArr);
}
module.exports = {
solve : solve
};