我喜欢F#难题,所以我尝试了这一个。希望你们喜欢。
let orgList = [(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)]
let orgMap =
orgList
|> List.fold (fun acc item ->
let key = snd item
match Map.tryFind key acc with
| Some(value) ->
let map' = Map.remove key acc
Map.add(key) (item::value) map'
| None ->
Map.add(key) (item::[]) acc
) Map.empty<int, (int*int) list>
let findReports supervisor =
let rec findReports' acc collection =
match collection with
| head::tail ->
(findReports' (head::acc) tail)
@ match Map.tryFind (fst head) orgMap with
| Some(value) -> (findReports' [] value)
| None -> []
| [] -> acc
findReports' [] (Map.find supervisor orgMap)
findReports 2
|> List.map fst
|> List.distinct
返回
val it : int list = [3; 4; 5; 7; 6]
findReports 2
返回
val it : (int * int) list = [(3, 2); (4, 2); (5, 3); (7, 3); (6, 4)]
我会分解它以便澄清。
let orgList = [ (1, 2); (1, 3); (1, 4); (2, 5); (3, 6); (4, 5); (5, 6); (5, 7) ]
我们将接收到的元组列表转换为一个以老板为键,值为((报告人,老板)列表)的函数映射。这也可以被称为邻接表,用于遍历图形。
let orgMap =
orgList
|> List.fold (fun acc item ->
let key = snd item
match Map.tryFind key acc with
如果有一份老板名下的报告列表,就将其添加到该列表中。
| Some(reports) ->
let map' = Map.remove key acc
Map.add(key) (item::reports) map'
否则,将其添加到空列表中并插入字典中。
| None ->
Map.add(key) (item::[]) acc
以一个空映射作为累加器开始。
) Map.empty<int, (int*int) list>
通过递归遍历项目以查找所有报告。
let findReports supervisor =
let rec findReports' acc collection =
match collection with
如果有一个项目,将其附加到累加器中。这是BFS。如果在连接运算符(@)之前和之后切换表达式,则会变成DFS。
| head::tail ->
(findReports' (head::acc) tail)
将当前列表连接到报告的递归列表以形成报告。
@ match Map.tryFind (fst head) orgMap with
| Some(value) -> (findReports' [] value)
| None -> []
如果在列表末尾,返回该列表。
| [] -> acc
运行递归函数。
findReports' [] (Map.find supervisor orgMap)
运行该函数。
findReports 7
只返回报告
|> List.map fst
不要重复报告已经报告过的问题。
|> List.distinct