leetcode 1091. 二进制矩阵中的最短路径

6 篇文章 0 订阅

在一个 N × N 的方形网格中,每个单元格有两种状态:空(0)或者阻塞(1)。

一条从左上角到右下角、长度为 k 的畅通路径,由满足下述条件的单元格 C_1, C_2, …, C_k 组成:

相邻单元格 C_i 和 C_{i+1} 在八个方向之一上连通(此时,C_i 和 C_{i+1} 不同且共享边或角)
C_1 位于 (0, 0)(即,值为 grid[0][0])
C_k 位于 (N-1, N-1)(即,值为 grid[N-1][N-1])
如果 C_i 位于 (r, c),则 grid[r][c] 为空(即,grid[r][c] == 0)
返回这条从左上角到右下角的最短畅通路径的长度。如果不存在这样的路径,返回 -1 。

输入:[[0,1],[1,0]]
输出:2

输入:[[0,0,0],[1,1,0],[1,1,0]]
输出:4

标准的bfs模板

class Solution {
        public  int shortestPathBinaryMatrix(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return -1;
        }
        // 如果起点就阻塞那就玩完啦
        if (grid[0][0]==1){
            return -1;
        }
        //定义 8个方向
        int[][] dir = {{1, -1}, {1, 0}, {1, 1}, {0,-1},{0,1},{-1,-1},{-1,0},{-1,1}};
        int m = grid.length;
        int n = grid[0].length;
        //bfs的老套路 来个队列
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{0,0});   //把起点扔进去
        grid[0][0] = 1;        // 把起点标记为阻塞
        int path = 1;     // 层数
        
        while (!queue.isEmpty()){
            int size = queue.size();
            while(size-- > 0){
                int[] cur = queue.poll();
                int x  = cur[0];
                int y  = cur[1];
                
                //能放进队列里的都是为0可以走的(这一点在后面保证了)
                // 如果等于终点则返回
                if (x == m-1 && y == n-1){    //
                    return path;
                }
                
                //开始八个方向的判断
                for (int[] d : dir){
                    int x1 = x + d[0];
                    int y1 = y + d[1];
                    //这里开始过滤
                    if (x1 < 0 || x1 >= m || y1 < 0||y1>=m || grid[x1][y1]==1){
                        continue;
                    }
                    //把在数组范围内 并且为0不阻塞的放入队列中
                    queue.add(new int[]{x1,y1});
                    grid[x1][y1] = 1; // 标记
                }
            }
            path++;  //遍历完一层 这时候要 ++啦
        }
        return -1;
    }
}

自己写的bfs

class Solution {
    public int shortestPathBinaryMatrix(int[][] grid) {
        if(grid[0][0]==1) return -1; 
        int[] x_size={0,0,-1,1,1,1,-1,-1};
        int[] y_size={-1,1,0,0,1,-1,1,-1};
        int[][] temp=new int[grid.length][grid[0].length];
            Queue<Integer> queue1=new LinkedList<>();
            Queue<Integer> queue2=new LinkedList<>();
            queue1.add(0);
            queue2.add(0);
            grid[0][0]=-1;
            while(!queue1.isEmpty()){
                int x=queue1.poll();
                int y=queue2.poll();
                if(x==grid.length-1 && y==grid[0].length-1) return -grid[x][y];
                for(int i=0;i<=7;i++){
                    int xx=x_size[i]+x;
                    int yy=y_size[i]+y;
                    if(xx<0 || yy<0 || xx>=grid.length || yy>=grid[0].length) continue;
                    if(grid[xx][yy]==0){
                        queue1.add(xx);
                        queue2.add(yy);
                        grid[xx][yy]=grid[x][y]-1;
                    }
                }
            }
            return -1;
    }
}

dfs也可以做,就是超时了,grid.length大了之后就会超时。明显不如bfs快,几个测试都没问题,仅供参考。

class Solution {
    int[][] grid;
    int ans=0x7fffffff;
    public  int shortestPathBinaryMatrix(int[][] grid) {
        this.grid=grid;
        dfs(0,0,1);//num=1表示第一步
        return ans==0x7fffffff?-1:ans;
    }
    public void dfs(int i,int j,int num){
        if(i<0 || j<0 || i>=grid.length || j>=grid[0].length || grid[i][j]!=0){
            return ;
        }
        if(i==grid.length-1 && j==grid[0].length-1){//到达了右下角
            if(num<ans) ans=num;//判断,并替换最优值
            return ;
        }
        grid[i][j]=1;//做标记防止二次访问

        dfs(i+1,j,num+1);
        dfs(i-1,j,num+1);
        dfs(i,j+1,num+1);
        dfs(i,j-1,num+1);
        dfs(i-1,j-1,num+1);
        dfs(i+1,j+1,num+1);
        dfs(i-1,j+1,num+1);
        dfs(i+1,j-1,num+1);

        grid[i][j]=0;//标记变回去
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值