|
| 1 | +// https://leetcode.com/problems/surrounded-regions |
| 2 | +// T: O(m * n) |
| 3 | +// S: O(m * n) |
| 4 | + |
| 5 | +import java.util.HashSet; |
| 6 | +import java.util.Set; |
| 7 | + |
| 8 | +public class SurroundedRegions { |
| 9 | + private record Position(int row, int column) { |
| 10 | + @Override |
| 11 | + public boolean equals(Object o) { |
| 12 | + if (this == o) return true; |
| 13 | + Position position = (Position) o; |
| 14 | + if (row != position.row) return false; |
| 15 | + return column == position.column; |
| 16 | + } |
| 17 | + |
| 18 | + @Override |
| 19 | + public int hashCode() { |
| 20 | + return 31 * row + column; |
| 21 | + } |
| 22 | + |
| 23 | + public Position top() { |
| 24 | + return new Position(row - 1, column); |
| 25 | + } |
| 26 | + |
| 27 | + public Position right() { |
| 28 | + return new Position(row, column + 1); |
| 29 | + } |
| 30 | + |
| 31 | + public Position bottom() { |
| 32 | + return new Position(row + 1, column); |
| 33 | + } |
| 34 | + |
| 35 | + public Position left() { |
| 36 | + return new Position(row, column - 1); |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + public void solve(char[][] board) { |
| 41 | + final Set<Position> visited = new HashSet<>(); |
| 42 | + final Set<Position> current = new HashSet<>(); |
| 43 | + final int rows = board.length, columns = board[0].length; |
| 44 | + |
| 45 | + for (int row = 1 ; row < rows - 1 ; row++) { |
| 46 | + for (int column = 1 ; column < columns - 1 ; column++) { |
| 47 | + if (board[row][column] == 'O') { |
| 48 | + final boolean isBorderRegion = markRegion(board, new Position(row, column), visited, current); |
| 49 | + if (!isBorderRegion) { |
| 50 | + captureRegion(board, current); |
| 51 | + } |
| 52 | + current.clear(); |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + private boolean markRegion(char[][] board, Position position, Set<Position> visited, Set<Position> region) { |
| 59 | + if (isInvalidPosition(board, position) || visited.contains(position) || isX(board, position)) return false; |
| 60 | + visited.add(position); |
| 61 | + region.add(position); |
| 62 | + boolean top = markRegion(board, position.top(), visited, region); |
| 63 | + boolean right = markRegion(board, position.right(), visited, region); |
| 64 | + boolean bottom = markRegion(board, position.bottom(), visited, region); |
| 65 | + boolean left = markRegion(board, position.left(), visited, region); |
| 66 | + return top || right || bottom || left || isBorderPosition(board, position); |
| 67 | + } |
| 68 | + |
| 69 | + private boolean isX(char[][] board, Position position) { |
| 70 | + return board[position.row][position.column] == 'X'; |
| 71 | + } |
| 72 | + |
| 73 | + private boolean isBorderPosition(char[][] board, Position position) { |
| 74 | + return position.row == 0 |
| 75 | + || position.row == board.length - 1 |
| 76 | + || position.column == 0 |
| 77 | + || position.column == board[0].length - 1; |
| 78 | + } |
| 79 | + |
| 80 | + private boolean isInvalidPosition(char[][] board, Position position) { |
| 81 | + return position.row < 0 |
| 82 | + || position.row >= board.length |
| 83 | + || position.column < 0 |
| 84 | + || position.column >= board[0].length; |
| 85 | + } |
| 86 | + |
| 87 | + private void captureRegion(char[][] board, Set<Position> positions) { |
| 88 | + for (Position position : positions) { |
| 89 | + board[position.row][position.column] = 'X'; |
| 90 | + } |
| 91 | + } |
| 92 | +} |
0 commit comments