在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)
现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。
返回必须翻转的 0 的最小数目。(可以保证答案至少是 1。)
示例 1:
输入:[[0,1],[1,0]]
输出:1
示例 2:
输入:[[0,1,0],[0,0,0],[0,0,1]]
输出:2
示例 3:
输入:[[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
提示:
1 <= A.length = A[0].length <= 100
A[i][j] == 0 或 A[i][j] == 1
思路:我们先用dfs找出来两个岛,之后通过bfs判断两岛之间的最短距离。
class Solution {
class node{
int r,c,d;
public node(int r,int c,int d) {
this.r=r;
this.c=c;
this.d=d;
}
}
public int shortestBridge(int[][] A) {
int m=A.length;
int n=A[0].length;
int[][] colors=get(A);
Queue<node> q=new LinkedList<>();
Set<Integer> target=new HashSet<>();
for(int i=0;i<m;i++)
for(int j=0;j<n;j++) {
if(colors[i][j]==1)
q.add(new node(i,j,0));
else if(colors[i][j]==2)
target.add(i*n+j);
}
while(!q.isEmpty()) {
node now=q.poll();
if(target.contains(now.r*n+now.c))
return now.d-1;
for(int nei : neighbor(A,now.r,now.c)) {
int r=nei/n,c=nei%n;
if(colors[r][c]!=1) {
q.add(new node(r,c,now.d+1));
colors[r][c]=1;
}
}
}
return -1;
}
private int[][] get(int[][] a){
int m=a.length;
int n=a[0].length;
int[][] colors=new int[m][n];
int t=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(colors[i][j]==0 && a[i][j]==1) {
Stack<Integer> st=new Stack<>();
st.push(i*n+j);
colors[i][j]=++t;
while(!st.isEmpty()) {
int node=st.pop();
int r=node/n,c=node%n;
for(int nei : neighbor(a,r,c)) {
int rr=nei/n,cc=nei%n;
if(a[rr][cc]==1 && colors[rr][cc]==0) {
colors[rr][cc]=t;
st.push(rr*n+cc);
}
}
}
}
return colors;
}
private List<Integer> neighbor(int[][] a,int r,int c){
int R=a.length;
int C=a[0].length;
List<Integer> ans=new ArrayList<>();
if(0<=r-1) ans.add((r-1)*R+c);
if(0<=c-1) ans.add(r*R+c-1);
if(r+1<R) ans.add((r+1)*R+c);
if(c+1<C) ans.add(r*R+c+1);
return ans;
}
}