
2025-02-11:合并两棵树后的最小直径。用go语言,给定两棵无向树,第一棵树有 n 个节点,第二棵树有 m 个节点,节点编号分别为 0 到 n-1 和 0 到 m-1。每棵树的边信息通过二维数组 edges1 和 edges2 表示,其中 edges1[i] = [ai, bi] 表示第一棵树中节点 ai 和 bi 之间存在一条边,而 edges2[i] = [ui, vi] 则表示第二棵树中节点 ui 和 vi 之间有一条边。
你的任务是从每棵树中选择一个节点,并通过一条新边将这两个节点连接起来。最终,你需要返回添加这条边之后新形成的树的最小直径。
在此,树的直径定义为任意两个节点之间的最长路径长度。
1 <= n, m <= 100000。
edges1.length == n - 1。
edges2.length == m - 1。
edges1[i].length == edges2[i].length == 2。
edges1[i] = [ai, bi]。
0 <= ai, bi < n。
edges2[i] = [ui, vi]。
0 <= ui, vi < m。
输入保证 edges1 和 edges2 分别表示一棵合法的树。
输入:edges1 = [[0,1],[0,2],[0,3]], edges2 = [[0,1]]。
输出:3。
解释:
将第一棵树中的节点 0 与第二棵树中的任意节点连接,得到一棵直径为 3 的树。
答案2025-02-11:
chatgpt
题目来自leetcode3203。
1.定义一个函数 diameter 用于计算树的直径。首先,构建两个邻接表 g 分别存储两棵树的边关系。然后定义一个递归内部函数 dfs 用于进行深度优先搜索(DFS)。
2.在 dfs 函数中,通过递归遍历树的节点,计算每个非父节点到根节点的最长路径。在遍历过程中更新直径的长度。
3.计算第一棵树和第二棵树的直径分别为 d1 和 d2。
4.计算合并后树的直径:
(d1+1)/2 + (d2+1)/2 + 1。5.输出返回合并后树的最小直径。
总的时间复杂度:
总的额外空间复杂度:
package main
import (
    "fmt"
)
func diameter(edges [][]int) (res int) {
    g := make([][]int, len(edges)+1)
    for _, e := range edges {
        x, y := e[0], e[1]
        g[x] = append(g[x], y)
        g[y] = append(g[y], x)
    }
    var dfs func(int, int)int
    dfs = func(x, fa int) (maxLen int) {
        for _, y := range g[x] {
            if y != fa {
                subLen := dfs(y, x) + 1
                res = max(res, maxLen+subLen)
                maxLen = max(maxLen, subLen)
            }
        }
        return
    }
    dfs(0, -1)
    return
}
func minimumDiameterAfterMerge(edges1, edges2 [][]int)int {
    d1 := diameter(edges1)
    d2 := diameter(edges2)
    return max(d1, d2, (d1+1)/2+(d2+1)/2+1)
}
func main() {
    edges1 := [][]int{{0, 1}, {0, 2}, {0, 3}}
    edges2 := [][]int{{0, 1}}
    result := minimumDiameterAfterMerge(edges1, edges2)
    fmt.Println(result)
}

use std::cmp;
fndiameter(edges: Vec<Vec<i32>>) ->i32 {
    letn = edges.len() + 1;
    letmut g = vec![Vec::new(); n];
    
    foredgein edges {
        letx = edge[0];
        lety = edge[1];
        g[x asusize].push(y);
        g[y asusize].push(x);
    }
    letmut res = 0;
    fndfs(x: i32, fa: i32, g: &Vec<Vec<i32>>, res: &muti32) ->i32 {
        letmut max_len = 0;
        for &y in &g[x asusize] {
            if y != fa {
                letsub_len = dfs(y, x, g, res) + 1;
                *res = cmp::max(*res, max_len + sub_len);
                max_len = cmp::max(max_len, sub_len);
            }
        }
        max_len
    }
    dfs(0, -1, &g, &mut res);
    res
}
fnminimum_diameter_after_merge(edges1: Vec<Vec<i32>>, edges2: Vec<Vec<i32>>) ->i32 {
    letd1 = diameter(edges1);
    letd2 = diameter(edges2);
    cmp::max(d1, cmp::max(d2, (d1 + 1) / 2 + (d2 + 1) / 2 + 1))
}
fnmain() {
    letedges1 = vec![vec![0, 1], vec![0, 2], vec![0, 3]];
    letedges2 = vec![vec![0, 1]];
    letresult = minimum_diameter_after_merge(edges1, edges2);
    println!("{}", result);
}
# -*-coding:utf-8-*-
defdiameter(edges):
    n = len(edges) + 1
    g = [[] for _ inrange(n)]
    
    for x, y in edges:
        g[x].append(y)
        g[y].append(x)
    
    res = 0
    defdfs(x, fa):
        nonlocal res
        max_len = 0
        for y in g[x]:
            if y != fa:
                sub_len = dfs(y, x) + 1
                res = max(res, max_len + sub_len)
                max_len = max(max_len, sub_len)
        return max_len
    dfs(0, -1)
    return res
defminimum_diameter_after_merge(edges1, edges2):
    d1 = diameter(edges1)
    d2 = diameter(edges2)
    returnmax(d1, d2, (d1 + 1) // 2 + (d2 + 1) // 2 + 1)
if __name__ == "__main__":
    edges1 = [[0, 1], [0, 2], [0, 3]]
    edges2 = [[0, 1]]
    result = minimum_diameter_after_merge(edges1, edges2)
    print(result)