如何解决JavaScript:使用 BFS 获取二进制矩阵中的最短路径
我一直在使用 JavaScript 研究 leetcode,我试图解决这个问题 https://leetcode.com/problems/shortest-path-in-binary-matrix/
这个问题要求返回距离或最短路径的长度,我解决了。这是我的答案
var shortestPathBinaryMatrix = function(grid) {
if(grid[0][0] != 0) return -1
const queue = [[[0,0],1]]
const dest = [grid.length - 1,grid[0].length - 1]
const visited = new Set()
const getNextSteps = ([x,y]) => {
const dirs = [[1,[-1,[0,1],-1],[1,-1]]
const nextSteps = []
for(const [nx,ny] of dirs) {
if(grid[x + nx]?.[y + ny] == 0) nextSteps.push([x + nx,y + ny])
}
return nextSteps
}
for(const [curr,distance] of queue) {
if(visited.has(curr.toString())) continue
if(curr[0] === dest[0] && curr[1] === dest[1] && grid[dest[0]][dest[1]] == 0) return distance
visited.add(curr.toString())
getNextSteps(curr).forEach(adj => queue.push([adj,distance + 1]))
}
return -1
};
但是我想知道我是否也可以获得到达矩阵末尾所需的实际路径,所以我不想返回一个数字作为路径的长度,而是返回一个坐标数组的实际路径它在短路径上访问。
例如,如果输入网格为[[0,1,0]]
,则应返回[ [ 0,0 ],[ 0,1 ],[ 1,2 ],[ 2,2 ] ]
但这比看起来更难。我尝试了几种方法,但似乎无法解决。有人可以试试吗?
解决方法
主要思想是使 visited
成为 Map 而不是 Set,并将前一个节点在到该访问节点的路径上的坐标注册为 value。
为此,我发现比您早一步制作已访问标记更容易:当您将单元格放入队列时进行标记,而不是在您将其从队列中拉出时进行标记.
到达目的地后,您可以将 Map 用作链表,然后沿着路径返回源节点。这样你就可以重建路径。然后只需要将其反转即可。
这是您的代码,其中带有注释标记的修改:
var shortestPathBinaryMatrix = function(grid) {
if(grid[0][0] != 0) return []; // modify return type
const queue = [[[0,0],1]];
const dest = [grid.length - 1,grid[0].length - 1];
const visited = new Map();
visited.set([0,0].toString(),null); // Mark source as visited
const getNextSteps = ([x,y]) => {
const dirs = [[1,[-1,[0,1],-1],[1,-1]];
const nextSteps = [];
for(const [nx,ny] of dirs) {
if(grid[x + nx]?.[y + ny] == 0) nextSteps.push([x + nx,y + ny]);
}
return nextSteps;
}
for (let [curr,distance] of queue) {
// Move the visited check to the loop
if (curr[0] === dest[0] && curr[1] === dest[1] && grid[dest[0]][dest[1]] == 0) {
// Derive the path from the linked list we now have in the visited structure:
let path = [];
while (curr) {
path.push(curr);
curr = visited.get(curr.toString());
}
return path.reverse(); // Need to reverse to get from source to destination
}
for (let adj of getNextSteps(curr)) {
// Visited-check moved here:
if (visited.has(adj.toString())) continue;
// Mark with the coordinates of the previous node on the path:
visited.set(adj.toString(),curr);
queue.push([adj,distance + 1]);
}
}
return []; // must modify this as well
};
// demo
let grid = [[0,1,0]];
let result = shortestPathBinaryMatrix(grid);
console.log(result);
无关:养成用分号结束语句的习惯是件好事。让您的代码依赖于 automatic semi-colon insertion algorithm 当然是可能的,但您不会是第一个陷入其中一个晦涩陷阱的人。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。