【算法练习】深度优先搜索

检查网格中是否存在有效路径

给你一个 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值