刷题题解-2 | 豆包MarsCode AI刷题

108 阅读4分钟

二进制矩阵中的最短畅通路径

1.题目

小R最近在玩一个迷宫游戏,游戏的目标是在一个 n x n 的二进制矩阵 grid 中找到一条从左上角 (0, 0) 到右下角 (n - 1, n - 1) 的畅通路径。畅通路径必须满足以下条件:

  1. 路径经过的所有单元格的值都是 0
  2. 路径中相邻的单元格必须在 8 个方向之一上连通(相邻单元格之间共享一条边或一个角)。

你需要帮助小R找到最短的畅通路径长度。如果不存在这样的路径,返回 -1

2.测试样例

样例1:

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

样例2:

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

样例3:

输入:grid = [[1,0,0],[1,1,0],[1,1,0]]
输出:-1

3.思路

典型的BFS问题,可以从(0,0)位置起始,进行BFS搜索,每次将队首元素的八个方向依次入队,判断这些位置是否合法,如果合法,加入到队列之中,同时更新距离,直至队列为空,最后判断从(0,0)(n-1,m-1)的距离是否为0,如果是0说明没有路径,否则即为最短路径的值。

算法步骤:

  • dist存储起点到其他各个点的距离。
  • 从起点开始广度优先遍历地图。
  • 当地图遍历完,就求出了起点到各个点的距离,输出dist[n-1][m-1]即可。

4.代码

import java.util.Arrays;
import java.util.Queue;
import java.util.LinkedList;

public class Main {

    //  一个内部类,用来存储每个位置的x,y坐标
    static class pair{
        private int x;
        private int y;

        public pair(int x, int y){
            this.x = x;
            this.y = y;
        }
    }

    public static int solution(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;

        // 判断特殊情况,如果只有一个元素且不为1,那么直接返回1即可
        if(n==1 && m==1 && grid[0][0]==0) return 1;

        // 如果起始位置和终点有一个是1,说明路径不畅通,返回-1
        if(grid[0][0]==1 || grid[n-1][m-1]==1) return -1;

        // x和y的八个偏移量
        int[] dx = {0, 1, 1, 1, 0, -1, -1, -1};
        int[] dy = {1, 1, 0, -1, -1, -1, 0, 1};

        // st代表(x,y)是否被使用过,dist代表起点到(x,y)的距离
        int[][] st = new int[n][m];
        for(int i=0; i<n; i++) Arrays.fill(st[i], 0);
        int[][] dist = new int[n][m];
        for(int i=0; i<n; i++) Arrays.fill(dist[i], 0);

        Queue<pair> q = new LinkedList<>();

        // 将起始位置入队
        q.add(new pair(0, 0));
        while(!q.isEmpty()){
            pair t = q.peek();
            q.poll();

            // 依次判断八个位置是否合法,如果非法则continue,否则入队,并将距离和状态更新
            for(int i=0; i<8; i++){
                int a = t.x + dx[i];
                int b = t.y + dy[i];

                if(a<0 || a>=n || b<0 || b>=m) continue;
                if(grid[a][b] == 1) continue;
                if(st[a][b] == 1) continue;

                dist[a][b] = dist[t.x][t.y] + 1;
                st[a][b] = 1;
                q.add(new pair(a, b));
            }
        }

        // 最后判断一下是否可以到达终点
        if(dist[n-1][m-1] == 0) return -1;

        return dist[n-1][m-1]+1;
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[][]{{0, 1}, {1, 0}}) == 2);
        System.out.println(solution(new int[][]{{0, 0, 0}, {1, 1, 0}, {1, 1, 0}}) == 4);
        System.out.println(solution(new int[][]{{1, 0, 0}, {1, 1, 0}, {1, 1, 0}}) == -1);
    }

}

image.png

二进制之和

1. 问题描述

小U和小R喜欢探索二进制数字的奥秘。他们想找到一个方法,将两个二进制字符串相加并以十进制的形式呈现。这个过程需要注意的是,他们的二进制串可能非常长,所以常规的方法可能无法处理大数。小U和小R希望你帮助他们设计一个算法,该算法能在保证时间复杂度不超过O(n^2)的前提下,返回两个二进制字符串的十进制求和结果。

2. 测试样例

样例1:

输入:binary1 = "101" ,binary2 = "110"
输出:'11'

样例2:

输入:binary1 = "111111" ,binary2 = "10100"
输出:'83'

样例3:

输入:binary1 = "111010101001001011" ,binary2 = "100010101001"
输出:'242420'

样例4:

输入:binary1 = "111010101001011" ,binary2 = "10010101001"
输出:'31220'

样例5:

输入:binary1 = "11" ,binary2 = "1"
输出:'4'

3. 解题思路

这道题如果用c/c++写的话就需要用到高精度算法来模拟加减的过程,但是如果用java或者python语言的话,这两种语言自带大数相加的功能,所以直接套用即可。

4. 代码

import java.math.BigInteger;

public class Main {

    public static String solution(String binary1, String binary2) {
        BigInteger num1 = new BigInteger(binary1, 2);
        BigInteger num2 = new BigInteger(binary2, 2);
        BigInteger sum = num1.add(num2);
        return sum.toString();
}

  
    public static void main(String[] args) {
        System.out.println(solution("101", "110").equals("11"));
        System.out.println(solution("111111", "10100").equals("83"));
        System.out.println(solution("111010101001001011","100010101001").equals("242420"));
    }

}

image.png