|
1 | 1 | package joshua.leetcode.bfs;
|
2 | 2 |
|
| 3 | +import joshua.leetcode.solutiontag.UnionFind; |
| 4 | + |
3 | 5 | public abstract class SurroundedRegions {
|
4 | 6 |
|
5 |
| - /** |
6 |
| - * Given a 2D board containing 'X' and 'O', capture all regions surrounded |
7 |
| - * by 'X'. |
8 |
| - * |
9 |
| - * A region is captured by flipping all 'O's into 'X's in that surrounded |
10 |
| - * region. |
11 |
| - * |
12 |
| - * For example, |
13 |
| - * X X X X |
14 |
| - * X O O X |
15 |
| - * X X O X |
16 |
| - * X O X X |
17 |
| - * |
18 |
| - * After running your function, the board should be: |
19 |
| - * X X X X |
20 |
| - * X X X X |
21 |
| - * X X X X |
22 |
| - * X O X X |
23 |
| - * |
24 |
| - * @param board |
25 |
| - */ |
26 |
| - public abstract void solve(char[][] board); |
27 |
| - |
28 |
| - public static void printArrays(char[][] arrays) { |
29 |
| - for (int i = 0; i < arrays.length; i++) { |
30 |
| - for (int j = 0; j < arrays[0].length; j++) { |
31 |
| - System.out.print(String.valueOf(arrays[i][j]) + '\t'); |
32 |
| - } |
33 |
| - System.out.println(); |
34 |
| - } |
35 |
| - } |
| 7 | + /** |
| 8 | + * Given a 2D board containing 'X' and 'O', capture all regions surrounded |
| 9 | + * by 'X'. |
| 10 | + * <p/> |
| 11 | + * A region is captured by flipping all 'O's into 'X's in that surrounded |
| 12 | + * region. |
| 13 | + * <p/> |
| 14 | + * For example, |
| 15 | + * X X X X |
| 16 | + * X O O X |
| 17 | + * X X O X |
| 18 | + * X O X X |
| 19 | + * <p/> |
| 20 | + * After running your function, the board should be: |
| 21 | + * X X X X |
| 22 | + * X X X X |
| 23 | + * X X X X |
| 24 | + * X O X X |
| 25 | + * |
| 26 | + * @param board |
| 27 | + */ |
| 28 | + public abstract void solve(char[][] board); |
| 29 | + |
| 30 | + public static void printArrays(char[][] arrays) { |
| 31 | + for (int i = 0; i < arrays.length; i++) { |
| 32 | + for (int j = 0; j < arrays[0].length; j++) { |
| 33 | + System.out.print(String.valueOf(arrays[i][j]) + '\t'); |
| 34 | + } |
| 35 | + System.out.println(); |
| 36 | + } |
| 37 | + } |
36 | 38 |
|
37 |
| - public static class Solution1 extends SurroundedRegions { |
| 39 | + @UnionFind |
| 40 | + public static class Solution1 extends SurroundedRegions { |
38 | 41 |
|
39 |
| - /** |
40 |
| - * union find algorithm. Observation: if an 'O' is not surrounded, it |
41 |
| - * has a path to a 'O' on the border. |
42 |
| - * Boolean[board.width*board.height], 1) find all the 'O's, tag all the |
43 |
| - * 'O's on the border; |
44 |
| - */ |
45 |
| - @Override |
46 |
| - public void solve(char[][] board) { |
47 |
| - if (board == null) |
48 |
| - return; |
49 |
| - if (board.length == 0 || board[0].length == 0) |
50 |
| - return; |
51 |
| - int height = board.length; |
52 |
| - int width = board[0].length; |
53 |
| - // every element's ultimate root on the path to border. |
54 |
| - int[] paths = new int[height * width]; |
55 |
| - // whether the element is connected to'O' on the border. |
56 |
| - Boolean[] connected = new Boolean[paths.length]; |
57 |
| - //initiation |
58 |
| - for(int idx=0;idx<paths.length;idx++){ |
59 |
| - int i=idx/width; |
60 |
| - int j=idx%width; |
61 |
| - paths[idx] = idx; |
62 |
| - char cur = board[i][j]; |
63 |
| - connected[idx]=cur == 'O' && (i == 0 || i == (height - 1) || j == 0 || j == (width - 1)); |
64 |
| - } |
65 |
| - // scan all the elements |
66 |
| - for(int idx=0;idx<paths.length;idx++){ |
67 |
| - int i=idx/width; |
68 |
| - int j=idx%width; |
69 |
| - char cur = board[i][j]; |
70 |
| - if (cur == 'X') |
71 |
| - continue; |
72 |
| - // the up one |
73 |
| - if (i > 0) { |
74 |
| - char up = board[i - 1][j]; |
75 |
| - if (up == 'O') { |
76 |
| - join(idx,idx-width,paths,connected); |
77 |
| - } |
78 |
| - } |
79 |
| - // the left one |
80 |
| - if (j > 0) { |
81 |
| - char left = board[i][j - 1]; |
82 |
| - if (left == 'O') { |
83 |
| - join(idx,idx-1,paths,connected); |
84 |
| - } |
85 |
| - } |
86 |
| - } |
87 |
| - // check all the 'O', if it's connected to the border, then it is |
88 |
| - // in surrounded region, otherwise change it as 'X' |
89 |
| - for(int idx=0;idx<paths.length;idx++){ |
90 |
| - int i=idx/width; |
91 |
| - int j=idx%width; |
92 |
| - char cur = board[i][j]; |
93 |
| - if (cur == 'X') |
94 |
| - continue; |
95 |
| - int root=findParent(idx,paths); |
96 |
| - if(connected[root]==true) |
97 |
| - continue; |
98 |
| - board[i][j]='X'; |
99 |
| - } |
100 |
| - } |
| 42 | + /** |
| 43 | + * union find algorithm. Observation: if an 'O' is not surrounded, it |
| 44 | + * has a path to a 'O' on the border. |
| 45 | + * Boolean[board.width*board.height], 1) find all the 'O's, tag all the |
| 46 | + * 'O's on the border; |
| 47 | + */ |
| 48 | + @Override |
| 49 | + public void solve(char[][] board) { |
| 50 | + if (board == null) |
| 51 | + return; |
| 52 | + if (board.length == 0 || board[0].length == 0) |
| 53 | + return; |
| 54 | + int height = board.length; |
| 55 | + int width = board[0].length; |
| 56 | + // every element's ultimate root on the path to border. |
| 57 | + int[] paths = new int[height * width]; |
| 58 | + // whether the element is connected to'O' on the border. |
| 59 | + Boolean[] connected = new Boolean[paths.length]; |
| 60 | + //initiation |
| 61 | + for (int idx = 0; idx < paths.length; idx++) { |
| 62 | + int i = idx / width; |
| 63 | + int j = idx % width; |
| 64 | + paths[idx] = idx; |
| 65 | + char cur = board[i][j]; |
| 66 | + connected[idx] = cur == 'O' && (i == 0 || i == (height - 1) || j == 0 || j == (width - 1)); |
| 67 | + } |
| 68 | + // scan all the elements |
| 69 | + for (int idx = 0; idx < paths.length; idx++) { |
| 70 | + int i = idx / width; |
| 71 | + int j = idx % width; |
| 72 | + char cur = board[i][j]; |
| 73 | + if (cur == 'X') |
| 74 | + continue; |
| 75 | + // the up one |
| 76 | + if (i > 0) { |
| 77 | + char up = board[i - 1][j]; |
| 78 | + if (up == 'O') { |
| 79 | + join(idx, idx - width, paths, connected); |
| 80 | + } |
| 81 | + } |
| 82 | + // the left one |
| 83 | + if (j > 0) { |
| 84 | + char left = board[i][j - 1]; |
| 85 | + if (left == 'O') { |
| 86 | + join(idx, idx - 1, paths, connected); |
| 87 | + } |
| 88 | + } |
| 89 | + } |
| 90 | + // check all the 'O', if it's connected to the border, then it is |
| 91 | + // in surrounded region, otherwise change it as 'X' |
| 92 | + for (int idx = 0; idx < paths.length; idx++) { |
| 93 | + int i = idx / width; |
| 94 | + int j = idx % width; |
| 95 | + char cur = board[i][j]; |
| 96 | + if (cur == 'X') |
| 97 | + continue; |
| 98 | + int root = findParent(idx, paths); |
| 99 | + if (connected[root] == true) |
| 100 | + continue; |
| 101 | + board[i][j] = 'X'; |
| 102 | + } |
| 103 | + } |
101 | 104 |
|
102 |
| - private void join(int i, int j, int[] paths,Boolean[] connected) { |
103 |
| - int iParent = findParent(i, paths); |
104 |
| - int jParent=findParent(j, paths); |
105 |
| - Boolean isConnected = connected[iParent]|| connected[jParent]; |
106 |
| - paths[iParent] = jParent; |
107 |
| - connected[jParent]=isConnected; |
108 |
| - } |
| 105 | + private void join(int i, int j, int[] paths, Boolean[] connected) { |
| 106 | + int iParent = findParent(i, paths); |
| 107 | + int jParent = findParent(j, paths); |
| 108 | + Boolean isConnected = connected[iParent] || connected[jParent]; |
| 109 | + paths[iParent] = jParent; |
| 110 | + connected[jParent] = isConnected; |
| 111 | + } |
109 | 112 |
|
110 | 113 |
|
111 |
| - private int findParent(int i, int[] paths) { |
112 |
| - while (paths[i] != i) |
113 |
| - i = paths[i]; |
114 |
| - return i; |
115 |
| - } |
| 114 | + private int findParent(int i, int[] paths) { |
| 115 | + while (paths[i] != i) |
| 116 | + i = paths[i]; |
| 117 | + return i; |
| 118 | + } |
116 | 119 |
|
117 |
| - } |
| 120 | + } |
118 | 121 |
|
119 | 122 | }
|
0 commit comments