深度优先搜索/广度优先搜索练习

该文章探讨了一种通过广度优先搜索(BFS)算法解决二维二进制数组中连接两座岛屿所需的最小0翻转次数的问题。通过遍历数组并标记已访问的元素,算法能有效地找到最短的连接路径。此外,文章还提到了这种方法在处理类似问题,如寻找二进制矩阵中最短路径的应用。
摘要由CSDN通过智能技术生成

文章目录

最短的桥

在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)

现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。

返回必须翻转的 0 的最小数目。(可以保证答案至少是 1 。)

示例 1:
输入:A = [[0,1],[1,0]]
输出:1

示例 2:
输入:A = [[0,1,0],[0,0,0],[0,0,1]]
输出:2

示例 3:
输入:A = [[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1

提示:

2 <= A.length == A[0].length <= 100
A[i][j] == 0 或 A[i][j] == 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-bridge
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

由于有两座岛,所以需要将第一座岛找到之后,利用广度优先搜索获取第一座岛到达第二座岛的最小距离
所以需要利用到队列这个数据结构,将距离第一座岛的大海(即原本数组的值为0的)压入队列中,然后更新它的值为3,表示大海。

对应的代码:

class Solution {
    public int shortestBridge(int[][] grid) {
        Queue<int[]> queue = new LinkedList<int[]>();//泛型是一个数组,用于存放第一座岛屿周围大海横坐标、纵坐标
        int level = 1,size,i,j,a,b;
        int[] tmp;//从队列中跳出的大海的位置
        int[] move_x = new int[]{0,-1,0,1};
        int[] move_y = new int[]{-1,0,1,0};
        boolean isFind = false;
        for(i = 0; i < grid.length; ++i){
            for(j = 0; j < grid[i].length; ++j){
                if(grid[i][j] == 1){
                    //如果值值为1,表示是岛屿,所以将和这座岛屿相邻的0压入到队列中
                    dfs(grid,queue,i,j);
                    //找到一座岛屿之后就退出循环
                    isFind = true;
                    break;
                }
            }
            if(isFind)//找到了第一座岛屿
               break;
        }
        while(!queue.isEmpty()){
            size = queue.size();
            //将第level个大海填充,然后将第level + 1个要填充的位置压入到队列中
            for(i = 0; i < size; ++i){
                 tmp = queue.poll();
                 for(j = 0; j < 4; ++j){
                     a = tmp[0] + move_x[j];
                     b = tmp[1] + move_y[j];
                     if(a < 0 || a >= grid.length || b < 0 || b >= grid[0].length || grid[a][b] >= 2)
                       continue;
                     if(grid[a][b] == 1)
                       return level;
                     queue.offer(new int[]{a,b});
                     /*
                     标记当前这个位置访问过了,如果没有这一步,则有可能导
                     致超时(因为有可能将已经访问过了的大海再次添加到队列
                     中
                     */
                     grid[a][b] = 3;
                 }
            }
            level++;
        }
        return 0;

    }
    /*
    找到第一座岛屿,并将这一座岛屿对应的值更新为2,从而在进行广度优先搜索
    的时候容易判断值为1是第二座岛
    */
    public void dfs(int[][] grid,Queue<int[]> queue,int x,int y){
        if(x < 0 || x >= grid.length || y < 0 || y >= grid[0].length || grid[x][y] >= 2)
          return;//如果grid[x][y]大于等于2,表示已经访问过了,直接返回
        if(grid[x][y] == 0){
           queue.offer(new int[]{x,y});
           grid[x][y] = 3;//标记已经被访问过了
           return;
        }
        grid[x][y] = 2;//将第一座岛屿的值值为2,区分第二座岛屿
        dfs(grid,queue,x,y - 1);
        dfs(grid,queue,x - 1,y);
        dfs(grid,queue,x ,y +1);
        dfs(grid,queue,x + 1,y);
    }
}

对应的结果:
在这里插入图片描述

与此题运用同样方法**(广度优先搜索)**的有:
二进制矩阵中的最短路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值