Skip to main content
Back to problems
#3203
Hard Algorithms

Find minimum diameter after merging two trees

Tree Depth-First Search Breadth-First Search Graph Theory
57.1% acceptance
Feb 25, 2026
695
39
There exist two undirected trees with n and m nodes, numbered from 0 to n - 1 and from 0 to m - 1, respectively. You are given two 2D integer arrays edges1 and edges2 of lengths n - 1 and m - 1, respectively, where edges1[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the first tree and edges2[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the second tree. You must connect one node from the first tree with another node from the second tree with an edge. Return the minimum possible diameter of the resulting tree. The diameter of a tree is the length of the longest path between any two nodes in the tree.

Solution

Rust
Time O(n * m)
Space O(n * m)
LeetCode
solution.rs
impl Solution {
  pub fn minimum_diameter_after_merge(edges1: Vec<Vec<i32>>, edges2: Vec<Vec<i32>>) -> i32 {
    let n = edges1.len() + 1;
    let m = edges2.len() + 1;
    let d1 = Self::tree_diameter(&edges1, n);
    let d2 = Self::tree_diameter(&edges2, m);
    // When we connect the two trees with one edge, the new diameter is:
    // max(d1, d2, ceil(d1/2) + ceil(d2/2) + 1)
    let merged = (d1 + 1) / 2 + (d2 + 1) / 2 + 1;
    d1.max(d2).max(merged)
  }

  fn tree_diameter(edges: &Vec<Vec<i32>>, n: usize) -> i32 {
    if n == 1 {
      return 0;
    }
    let mut adj = vec![vec![]; n];
    for e in edges {
      let (u, v) = (e[0] as usize, e[1] as usize);
      adj[u].push(v);
      adj[v].push(u);
    }
    // Two BFS to find diameter
    let (far1, _) = Self::bfs(&adj, 0);
    let (_, d) = Self::bfs(&adj, far1);
    d
  }

  fn bfs(adj: &Vec<Vec<usize>>, start: usize) -> (usize, i32) {
    let n = adj.len();
    let mut dist = vec![-1i32; n];
    dist[start] = 0;
    let mut queue = std::collections::VecDeque::new();
    queue.push_back(start);
    let mut farthest = start;
    while let Some(u) = queue.pop_front() {
      for &v in &adj[u] {
        if dist[v] == -1 {
          dist[v] = dist[u] + 1;
          if dist[v] > dist[farthest] {
            farthest = v;
          }
          queue.push_back(v);
        }
      }
    }
    (farthest, dist[farthest])
  }
}