-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOceanWaterFlow.java
119 lines (96 loc) · 3.98 KB
/
OceanWaterFlow.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
/*
Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent,
the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right
and bottom edges.
Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.
Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.
Note:
The order of returned grid coordinates does not matter.
Both m and n are less than 150.
Example:
Given the following 5x5 matrix:
Pacific ~ ~ ~ ~ ~
~ 1 2 2 3 (5) *
~ 3 2 3 (4) (4) *
~ 2 4 (5) 3 1 *
~ (6) (7) 1 4 5 *
~ (5) 1 1 2 4 *
* * * * * Atlantic
Return:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
Author: Erich Meissner
Date: 3/25/21
Time: 7:42 PM
*/
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
public class OceanWaterFlow {
public static void main(String[] args) {
}
private static final int[][] DIRECTIONS = new int[][]{{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
private int numRows;
private int numCols;
private int[][] landHeights;
public List<List<Integer>> pacificAtlantic(int[][] matrix) {
// Check if input is empty
if (matrix.length == 0 || matrix[0].length == 0) {
return new ArrayList<>();
}
// Save initial values to parameters
numRows = matrix.length;
numCols = matrix[0].length;
landHeights = matrix;
// Setup each queue with cells adjacent to their respective ocean
Queue<int[]> pacificQueue = new LinkedList<>();
Queue<int[]> atlanticQueue = new LinkedList<>();
for (int i = 0; i < numRows; i++) {
pacificQueue.offer(new int[]{i, 0});
atlanticQueue.offer(new int[]{i, numCols - 1});
}
for (int i = 0; i < numCols; i++) {
pacificQueue.offer(new int[]{0, i});
atlanticQueue.offer(new int[]{numRows - 1, i});
}
// Perform a BFS for each ocean to find all cells accessible by each ocean
boolean[][] pacificReachable = bfs(pacificQueue);
boolean[][] atlanticReachable = bfs(atlanticQueue);
// Find all cells that can reach both oceans
List<List<Integer>> commonCells = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
if (pacificReachable[i][j] && atlanticReachable[i][j]) {
commonCells.add(List.of(i, j));
}
}
}
return commonCells;
}
private boolean[][] bfs(Queue<int[]> queue) {
boolean[][] reachable = new boolean[numRows][numCols];
while (!queue.isEmpty()) {
int[] cell = queue.poll();
// This cell is reachable, so mark it
reachable[cell[0]][cell[1]] = true;
for (int[] dir : DIRECTIONS) { // Check all 4 directions
int newRow = cell[0] + dir[0];
int newCol = cell[1] + dir[1];
// Check if new cell is within bounds
if (newRow < 0 || newRow >= numRows || newCol < 0 || newCol >= numCols) {
continue;
}
// Check that the new cell hasn't already been visited
if (reachable[newRow][newCol]) {
continue;
}
// Check that the new cell has a higher or equal height,
// So that water can flow from the new cell to the old cell
if (landHeights[newRow][newCol] < landHeights[cell[0]][cell[1]]) {
continue;
}
// If we've gotten this far, that means the new cell is reachable
queue.offer(new int[]{newRow, newCol});
}
}
return reachable;
}