URL
https://leetcode.com/problems/find-minimum-diameter-after-merging-two-trees/description/?envType=daily-question&envId=2024-12-24
Code
https://github.com/syohex/dotnet-study/blob/master/fsharp/leetcode/challenge/202412/find_minimum_diameter_after_merging_two_trees/main.fsx
open System
let toGraph edges =
let rec toGraph' edges acc =
match edges with
| [] -> acc
| (n1, n2) :: t ->
let acc =
match Map.tryFind n1 acc with
| Some(v) -> Map.add n1 (n2 :: v) acc
| None -> Map.add n1 [ n2 ] acc
let acc =
match Map.tryFind n2 acc with
| Some(v) -> Map.add n2 (n1 :: v) acc
| None -> Map.add n2 [ n1 ] acc
toGraph' t acc
toGraph' edges Map.empty
let getDiameter initNode graph =
let rec getDiameter' q graph visited furtherestNode acc =
match q with
| [] -> acc, furtherestNode
| _ ->
let visited = q |> List.fold (fun acc node -> Set.add node acc) visited
let furtherestNode = List.head q
let q =
q
|> List.fold
(fun acc node ->
match Map.tryFind node graph with
| None -> acc
| Some(v) -> v @ acc)
[]
|> List.filter (fun node -> not <| Set.contains node visited)
let acc = if List.isEmpty q then acc else acc + 1
getDiameter' q graph visited furtherestNode acc
getDiameter' [ initNode ] graph Set.empty initNode 0
let getLongtestDiameter graph =
let _, furtherestNode = getDiameter 0 graph
getDiameter furtherestNode graph |> fst
let minimumDiameterAfterMerge (edges1: (int * int) list) (edges2: (int * int) list) : int =
let graph1 = toGraph edges1
let graph2 = toGraph edges2
let diameter1 = getLongtestDiameter graph1
let diameter2 = getLongtestDiameter graph2
let longest = max diameter1 diameter2
let halfDiameter = double >> (fun n -> n / 2.0) >> Math.Ceiling >> int
let mergedDiameter = halfDiameter diameter1 + halfDiameter diameter2 + 1
max longest mergedDiameter