检查网格中是否存在有效路径
给你一个 m x n
的网格 grid。网格里的每个单元都代表一条街道。grid[i][j]
的街道可以是:
1
表示连接左单元格和右单元格的街道。
2
表示连接上单元格和下单元格的街道。
3
表示连接左单元格和下单元格的街道。
4
表示连接右单元格和下单元格的街道。
5
表示连接左单元格和上单元格的街道。
6
表示连接右单元格和上单元格的街道。
你最开始从左上角的单元格 (0,0)
开始出发,网格中的「有效路径」是指从左上方的单元格 (0,0)
开始、一直到右下方的(m-1,n-1)
结束的路径。该路径必须只沿着街道走。
示例 1:
输入:grid = [[2,4,3],[6,5,2]]
输出:true
解释:如图所示,你可以从 (0, 0) 开始,访问网格中的所有单元格并到达 (m - 1, n - 1) 。
示例 2:
输入:grid = [[1,2,1],[1,2,1]]
输出:false
解释:如图所示,单元格 (0, 0) 上的街道没有与任何其他单元格上的街道相连,你只会停在 (0, 0) 处。
深度优先搜索
const pipe = [
[-1,-1,-1,-1],
[-1,-1,2,3],
[0,1,-1,-1],
[2,-1,-1,1],
[3,-1,1,-1],
[-1,2,-1,0],
[-1,3,0,-1]
]
const dx = [-1,1,0,0];
const dy = [0,0,-1,1];
function hasValidPath(grid) {
var m = grid.length;
var n = grid[0].length;
var nstreet = grid[0][0];
function dfs(x,y,dir,grid){
if(x==m-1 && y==n-1) return true;
var xx = x+dx[dir];
var yy = y+dy[dir];
if(xx<0||yy<0||xx>=m||yy>=n) return false;
var nxtstreet = grid[xx][yy];
if(pipe[nxtstreet][dir]!==-1) return dfs(xx,yy,pipe[nxtstreet][dir],grid);
return false;
}
for(var i=0;i<4;i++){
if(pipe[nstreet][i]!==-1){
if(dfs(0,0,pipe[nstreet][i],grid)) return true;
}
}
return false;
};
var grid = [[2,4,3],[6,5,2]];
grid = [[4,3,3],[6,5,2]]
var res = hasValidPath(grid);
console.log(res);
grid=[[2,4,3],[6,5,2]]
时,OK。
但grid=[[4,3,3],[6,5,2]]
时,有环,所以Maximum call stack size exceeded
。
第一次修改:解决环的问题
function hasValidPath(grid) {
var m = grid.length;
var n = grid[0].length;
var nstreet = grid[0][0];
var visit=[];
for(var i=0;i<301;i++){
visit[i] = [];
for(var j=0;j<301;j++){
visit[i][j] = false;
}
}
function dfs(x,y,dir,grid){
visit[x][y] = true;
if(x==m-1 && y==n-1) return true;
var xx = x+dx[dir];
var yy = y+dy[dir];
if(xx<0||yy<0||xx>=m||yy>=n) return false;
var nxtstreet = grid[xx][yy];
if(pipe[nxtstreet][dir]!==-1 && !visit[xx][yy]) return dfs(xx,yy,pipe[nxtstreet][dir],grid);
return false;
}
for(var i=0;i<4;i++){
if(pipe[nstreet][i]!==-1){
if(dfs(0,0,pipe[nstreet][i],grid)) return true;
}
}
return false;
};
grid=[[4,3,3],[6,5,2]]
时,将返回false
,解决了环的问题。
但是,数据量大时导致递归深度太深,栈溢出了。
第二次修改:使用双队列
function hasValidPath(grid) {
var m = grid.length;
var n = grid[0].length;
var nstreet = grid[0][0];
var visit=[];
function resetVisit(){
for(var i=0;i<301;i++){
visit[i] = [];
for(var j=0;j<301;j++){
visit[i][j] = false;
}
}
}
resetVisit();
var queue = [];
for(var i=0;i<4;i++){
if(pipe[nstreet][i]!==-1){
queue.push([0,0,pipe[nstreet][i]]);
}
}
while(queue.length>0){
var queue2 = [queue.shift()];
while(queue2.length>0){
var [x,y,dir] = queue2.shift();
visit[x][y] = true;
if(x===m-1 && y===n-1) return true;
var xx = x + dx[dir];
var yy = y + dy[dir];
if(xx<0 || yy<0 || xx>=m || yy>=n) continue;
nstreet = grid[xx][yy];
if(pipe[nstreet][dir]!=-1 && !visit[xx][yy]) {
queue2.push([xx,yy,pipe[nstreet][dir]])
}
}
resetVisit();
}
return false;
};
本练习来自leetcode