LeetCode 1129. Shortest Path with Alternating Colors in F#
URL
https://leetcode.com/problems/shortest-path-with-alternating-colors/
Code
https://github.com/syohex/dotnet-study/blob/master/fsharp/leetcode/problems/1129/main.fsx
let edgesToGraph (edges: (int * int) list) : Map<int, int list> =
let rec edgesToGraph' edges acc =
match edges with
| [] -> acc
| (src, dest) :: t ->
match Map.tryFind src acc with
| Some (v) -> edgesToGraph' t (Map.add src (dest :: v) acc)
| None -> edgesToGraph' t (Map.add src [ dest ] acc)
edgesToGraph' edges Map.empty
let rec shortestAlternatingPaths'
(q: (int * bool) list)
steps
(redGraph: Map<int, int list>)
(blueGraph: Map<int, int list>)
(redVisited: bool [])
(blueVisited: bool [])
(acc: int [])
: int [] =
match q with
| [] -> acc
| _ ->
q
|> List.iter (fun (n, _) -> if acc.[n] = -1 then acc.[n] <- steps)
let q' =
q
|> List.fold
(fun acc (node, isRed) ->
let visited =
if isRed then
blueVisited
else
redVisited
let graph = if isRed then blueGraph else redGraph
match Map.tryFind node graph with
| None -> acc
| Some (nexts) ->
let nexts' =
nexts
|> List.filter (fun n -> not visited.[n])
|> List.map (fun n -> n, not isRed)
nexts'
|> List.iter (fun (n, _) -> visited.[n] <- true)
nexts' @ acc)
[]
shortestAlternatingPaths' q' (steps + 1) redGraph blueGraph redVisited blueVisited acc
let shortestAlternatingPaths (n: int) (redEdges: (int * int) list) (blueEdges: (int * int) list) : int [] =
let redGraph = edgesToGraph redEdges
let blueGraph = edgesToGraph blueEdges
let redVisited = Array.init n (fun _ -> false)
let blueVisited = Array.init n (fun _ -> false)
let redHasZero = Map.tryFind 0 redGraph |> Option.isSome
let blueHasZero = Map.tryFind 0 blueGraph |> Option.isSome
let ret = Array.init n (fun _ -> -1)
ret.[0] <- 0
let q =
match redHasZero, blueHasZero with
| true, true -> [ (0, false); (0, true) ]
| true, false -> [ (0, false) ]
| false, true -> [ 0, true ]
| false, false -> []
shortestAlternatingPaths' q 0 redGraph blueGraph redVisited blueVisited ret