题目描述
给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。
岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中恰好存在两座岛 。
你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。
返回必须翻转的 0 的最小数目。
示例 1:
输入:grid = [[0,1],[1,0]]
输出:1
示例 2:
输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:2
示例 3:
输入:grid = [[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
提示:
n == grid.length == grid[i].length
2 <= n <= 100
grid[i][j] 为 0 或 1
grid 中恰有两个岛
解题思路
- 这道题目我们通过DFS+BFS的方式来求解,首先我们通过DFS先来求得一座岛,然后进行标记,防止重复走,然后在通过BFS一层一层来进行遍历,每次遍历一层,计数器加1,知道我们在遍历的过程中遇到了另外一个岛屿,也就是1的位置。
实现代码
class Solution {
public int shortestBridge(int[][] grid) {
int n=grid.length;
int[][] dir={{-1,0},{1,0},{0,1},{0,-1}};
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){
LinkedList<int[]> queue=new LinkedList<>();
dfs(i,j,grid,queue);
int cnt=0;
while(!queue.isEmpty()){
int size=queue.size();
for(int k=0;k<size;k++){
int[] num=queue.pollFirst();
int x=num[0],y=num[1];
for(int d=0;d<4;d++){
int curX=x+dir[d][0];
int curY=y+dir[d][1];
if(curX>=0&&curY>=0&&curX<n&&curY<n){
if(grid[curX][curY]==0){
queue.addLast(new int[]{curX,curY});
grid[curX][curY]=-1;
}else if(grid[curX][curY]==1){
return cnt;
}
}
}
}
cnt++;
}
}
}
}
return 0;
}
public void dfs(int i,int j,int[][] grid,LinkedList<int[]> queue){
int n=grid.length,m=grid[0].length;
if(i<0||i>=n||j<0||j>=m||grid[i][j]!=1){
return;
}
grid[i][j]=-1;
queue.addLast(new int[]{i,j});
dfs(i-1,j,grid,queue);
dfs(i+1,j,grid,queue);
dfs(i,j-1,grid,queue);
dfs(i,j+1,grid,queue);
}
}