-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathShortestBridge.java
197 lines (180 loc) · 6.49 KB
/
ShortestBridge.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package LeetCodeJava.BFS;
// https://leetcode.com/problems/shortest-bridge/description/
import java.util.ArrayList;
import java.util.List;
/**
* 934. Shortest Bridge
* Medium
* Topics
* Companies
* You are given an n x n binary matrix grid where 1 represents land and 0 represents water.
*
* An island is a 4-directionally connected group of 1's not connected to any other 1's. There are exactly two islands in grid.
*
* You may change 0's to 1's to connect the two islands to form one island.
*
* Return the smallest number of 0's you must flip to connect the two islands.
*
*
*
* Example 1:
*
* Input: grid = [[0,1],[1,0]]
* Output: 1
* Example 2:
*
* Input: grid = [[0,1,0],[0,0,0],[0,0,1]]
* Output: 2
* Example 3:
*
* Input: 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]]
* Output: 1
*
*
* Constraints:
*
* n == grid.length == grid[i].length
* 2 <= n <= 100
* grid[i][j] is either 0 or 1.
* There are exactly two islands in grid.
*/
public class ShortestBridge {
// V0
// public int shortestBridge(int[][] grid) {
//
// }
// V1-1
// https://leetcode.com/problems/shortest-bridge/editorial/
// IDEA: Depth-First-Search + Breadth-First-Search
private List<int[]> bfsQueue;
// Recursively check the neighboring land cell of current cell grid[x][y] and
// add all
// land cells of island A to bfsQueue.
private void dfs(int[][] grid, int x, int y, int n) {
grid[x][y] = 2;
bfsQueue.add(new int[] { x, y });
for (int[] pair : new int[][] { { x + 1, y }, { x - 1, y }, { x, y + 1 }, { x, y - 1 } }) {
int curX = pair[0], curY = pair[1];
if (0 <= curX && curX < n && 0 <= curY && curY < n && grid[curX][curY] == 1) {
dfs(grid, curX, curY, n);
}
}
}
// Find any land cell, and we treat it as a cell of island A.
public int shortestBridge_1_1(int[][] grid) {
int n = grid.length;
int firstX = -1, firstY = -1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
firstX = i;
firstY = j;
break;
}
}
}
// Add all land cells of island A to bfsQueue.
bfsQueue = new ArrayList<>();
dfs(grid, firstX, firstY, n);
int distance = 0;
while (!bfsQueue.isEmpty()) {
List<int[]> newBfs = new ArrayList<>();
for (int[] pair : bfsQueue) {
int x = pair[0], y = pair[1];
for (int[] nextPair : new int[][] { { x + 1, y }, { x - 1, y }, { x, y + 1 }, { x, y - 1 } }) {
int curX = nextPair[0], curY = nextPair[1];
if (0 <= curX && curX < n && 0 <= curY && curY < n) {
if (grid[curX][curY] == 1) {
return distance;
} else if (grid[curX][curY] == 0) {
newBfs.add(nextPair);
grid[curX][curY] = -1;
}
}
}
}
// Once we finish one round without finding land cells of island B, we will
// start the next round on all water cells that are 1 cell further away from
// island A and increment the distance by 1.
bfsQueue = newBfs;
distance++;
}
return distance;
}
// V1-2
// https://leetcode.com/problems/shortest-bridge/editorial/
// IDEA: BFS
public int shortestBridge_1_2(int[][] grid) {
int n = grid.length;
int firstX = -1, firstY = -1;
// Find any land cell, and we treat it as a cell of island A.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
firstX = i;
firstY = j;
break;
}
}
}
// bfsQueue for BFS on land cells of island A; secondBfsQueue for BFS on water
// cells.
/**
* NOTE !!!
*
* -> bfsQueue for BFS on land cells of island A
*
* -> secondBfsQueue for BFS on water cell
*/
List<int[]> bfsQueue = new ArrayList<>();
List<int[]> secondBfsQueue = new ArrayList<>();
bfsQueue.add(new int[] { firstX, firstY });
secondBfsQueue.add(new int[] { firstX, firstY });
grid[firstX][firstY] = 2;
// BFS for all land cells of island A and add them to secondBfsQueue.
while (!bfsQueue.isEmpty()) {
List<int[]> newBfs = new ArrayList<>();
for (int[] cell : bfsQueue) {
int x = cell[0];
int y = cell[1];
for (int[] next : new int[][] { { x + 1, y }, { x - 1, y }, { x, y + 1 }, { x, y - 1 } }) {
int curX = next[0];
int curY = next[1];
if (curX >= 0 && curX < n && curY >= 0 && curY < n && grid[curX][curY] == 1) {
newBfs.add(new int[] { curX, curY });
secondBfsQueue.add(new int[] { curX, curY });
grid[curX][curY] = 2;
}
}
}
bfsQueue = newBfs;
}
int distance = 0;
while (!secondBfsQueue.isEmpty()) {
List<int[]> newBfs = new ArrayList<>();
for (int[] cell : secondBfsQueue) {
int x = cell[0];
int y = cell[1];
for (int[] next : new int[][] { { x + 1, y }, { x - 1, y }, { x, y + 1 }, { x, y - 1 } }) {
int curX = next[0];
int curY = next[1];
if (curX >= 0 && curX < n && curY >= 0 && curY < n) {
if (grid[curX][curY] == 1) {
return distance;
} else if (grid[curX][curY] == 0) {
newBfs.add(new int[] { curX, curY });
grid[curX][curY] = -1;
}
}
}
}
// Once we finish one round without finding land cells of island B, we will
// start the next round on all water cells that are 1 cell further away from
// island A and increment the distance by 1.
secondBfsQueue = newBfs;
distance++;
}
return distance;
}
// V2
}