Formatted question description: https://leetcode.ca/all/934.html

# 934. Shortest Bridge

Medium

## Description

In a given 2D binary array A, there are two islands. (An island is a 4-directionally connected group of 1s not connected to any other 1s.)

Now, we may change 0s to 1s so as to connect the two islands together to form 1 island.

Return the smallest number of 0s that must be flipped. (It is guaranteed that the answer is at least 1.)

Example 1:

Input: [[0,1],[1,0]]

Output: 1

Example 2:

Input: [[0,1,0],[0,0,0],[0,0,1]]

Output: 2

Example 3:

Input: [[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]]

Output: 1

Note:

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

## Solution

Do two rounds of breadth first search.

In the first round, loop over the 2D array A and find the first occurrence of 1, and do breadth first search starting from this occurrence of 1. For all the cells with 1 that can be reached, including the starting cell, replace all the 1’s with 2’s, so that this island is different from the other island that has not been visited.

In the second round, do breadth first search starting from all the cells in the first island. If a 1 is met, then the shortest distance between the two islands is found. The length of the shortest bridge equals the shortest distance minus 1.

class Solution {
public int shortestBridge(int[][] A) {
if (A == null || A.length <= 1)
return 0;
int sideLength = A.length;
int islandRow = -1, islandColumn = -1;
outer:
for (int i = 0; i < sideLength; i++) {
for (int j = 0; j < sideLength; j++) {
if (A[i][j] == 1) {
islandRow = i;
islandColumn = j;
break outer;
}
}
}
List<int[]> cells = breadthFirstSearch(A, islandRow, islandColumn);
return minDistance - 1;
}

public List<int[]> breadthFirstSearch(int[][] array, int row, int column) {
final int WHITE = 0;
final int GRAY = 1;
final int BLACK = 2;
List<int[]> cells = new ArrayList<int[]>();
int sideLength = array.length;
int[][] colors = new int[sideLength][sideLength];
colors[row][column] = GRAY;
int[][] directions = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue.offer(new int[]{row, column});
while (!queue.isEmpty()) {
int[] cell = queue.poll();
int curRow = cell, curColumn = cell;
array[curRow][curColumn] = 2;
for (int[] direction : directions) {
int newRow = curRow + direction, newColumn = curColumn + direction;
if (newRow >= 0 && newRow < sideLength && newColumn >= 0 && newColumn < sideLength) {
if (array[newRow][newColumn] == 1 && colors[newRow][newColumn] == WHITE) {
colors[newRow][newColumn] = GRAY;
queue.offer(new int[]{newRow, newColumn});
}
}
}
colors[curRow][curColumn] = BLACK;
}
return cells;
}

public int breadthFirstSearch(int[][] array, List<int[]> cells) {
final int WHITE = 0;
final int GRAY = 1;
final int BLACK = 2;
int sideLength = array.length;
int[][] colors = new int[sideLength][sideLength];
int distance = 0;
int[][] directions = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
for (int[] cell : cells) {
colors[cell][cell] = GRAY;
queue.offer(cell);
}
while (!queue.isEmpty()) {
distance++;
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] cell = queue.poll();
int row = cell, column = cell;
for (int[] direction : directions) {
int newRow = row + direction, newColumn = column + direction;
if (newRow >= 0 && newRow < sideLength && newColumn >= 0 && newColumn < sideLength) {
if (array[newRow][newColumn] == 1)
return distance;
else if (array[newRow][newColumn] != 2 && colors[newRow][newColumn] == WHITE) {
colors[newRow][newColumn] = GRAY;
queue.offer(new int[]{newRow, newColumn});
}
}
}
}
}
return distance;
}
}