问题描述
这是一个问题,可以使用每条边上具有不同成本的有向图进行建模。
我们的输入是一个边数组。
const edges = [['A','B',20],['B','C',10],['A',50],'D',5],['D',2]]
['A',
表示从 A
到 B
的成本是 20。我想编写一个函数,返回给定地点到另一个成本最低的地点之间的路径。请注意,此图中没有循环。
在这种情况下,如果起点是A
,目的地是C
,那么有三种方式可以去
path 1: A => C - cost 50
path 2: A => B => C - cost 30
path 3: A => B => D => C - cost 27
所以函数应该返回具有最小成本的路径,即 A,B,D,C
这是我的尝试:
function bar(edges,start,end) {
const paths = []
const visited = new Map()
const graph = edges.reduce((map,[start,end,cost]) => {
if(map.has(start)) {
map.get(start).push([end,cost])
} else {
map.set(start,[[end,cost]])
}
return map
},new Map())
const queue = [[start,0]]
for(const [node,costSofar] of queue) {
if(node === end) {
let pointer = node
const path = []
while(pointer) {
path.push(pointer)
pointer = visited.get(pointer)
}
paths.push([path.reverse().join(','),costSofar])
continue
}
graph.get(node).forEach(([dest,localCost]) => {
// this part ? is problematic
visited.set(dest,node)
queue.push([dest,localCost + costSofar])
})
}
return paths.sort(([pathA,costA],[pathB,costB]) => costA - costB)[0]
}
所以我使用邻接表来表示图,即
{
A: [['B',['C',50]]
B: [['C',5]]
D: [['C',2]]
}
然后我使用广度优先搜索来探索图形并记录路径,一旦我们到达目的地,我们将路径添加到 paths
。顺便说一句,我知道 Dijkstra 算法,但是,如果我错了,请纠正我,我觉得因为这个图没有循环,所以我们可以使用普通的 bfs 来解决它。
我的问题是,我的函数实际上有一个错误,虽然它确实捕获了所有具有相应成本的路径,但路径并非 100% 正确。如果您注销函数的 return 语句,即 paths.sort(([pathA,costB]) => costA - costB)
,您将看到此处的值为 [ [ 'A,C',27 ],[ 'A,30 ],50 ] ]
。前两个是正确的,但最后一个应该是 ['A',50]
。我认为问题是由填充 visited
地图的方式引起的,但我不知道如何解决该问题。
解决方法
因为您希望为每条可能的路径维护单独的路径信息,即使一条路径稍后拦截另一条路径,具有 visited
映射(其中键是目标节点)不会起作用,因为 {{1} } 会覆盖之前路径的信息。
最后我没有使用 visited.set
在循环中获取指针,而是在迭代时获取 visited
Map 的节点信息。递归会有所帮助。
graph