[LintCode] Surrounded Regions

Given a 2D board containing ‘X‘ and ‘O‘, capture all regions surrounded by ‘X‘.

A region is captured by flipping all ‘O‘‘s into ‘X‘‘s in that surrounded region.

Have you met this question in a real interview?

Yes

Example

X X X X
X O O X
X X O X
X O X X

After capture all regions surrounded by ‘X‘, the board should be:

X X X X
X X X X
X X X X
X O X X

Solution 1. BFS, O(n * m) runtime, O(n * m) space

For each unvisited cell of ‘O‘, do a bfs and add all connected && unvisited cells of ‘O‘ to a list. If at any point, we determine that a cell of ‘O‘ is on one of the four edges of the board,

mark the flag surrounded to false as this whole list of ‘O‘s are not surrounded by ‘X‘. Otherwise, set it to true.

For each list, if the flag surrounded is true, change all the cells in this list to ‘X‘.

Runtime analysis: each cell is visited at most two times, first time for all cells, second time for cells that are ‘O‘ and surrounded by ‘X‘, so O(n * m).

This solution is pretty straightforward, but it must use extra O(n * m) memory to keep track if a cell has been visited and save all connected cells of ‘O‘.

 1 public class Solution {
 2     private class Point {
 3         int x, y;
 4         Point(int x, int y){
 5             this.x = x;
 6             this.y = y;
 7         }
 8     }
 9     public void surroundedRegions(char[][] board) {
10         if(board == null || board.length == 0 || board[0].length == 0){
11             return;
12         }
13         int n = board.length, m = board[0].length;
14         boolean[][] visited = new boolean[n][m];
15
16         for(int i = 0; i < n; i++){
17             for(int j = 0; j < m; j++){
18                 if(visited[i][j] == false && board[i][j] == ‘O‘){
19                     ArrayList<Point> points = new ArrayList<Point>();
20                     if(bfsHelper(board, i, j, points, visited)){
21                         for(int k = 0; k < points.size(); k++){
22                             board[points.get(k).x][points.get(k).y] = ‘X‘;
23                         }
24                     }
25                 }
26             }
27         }
28     }
29     private boolean bfsHelper(char[][] board, int i, int j,
30                             ArrayList<Point> points,
31                             boolean[][] visited){
32         boolean surrounded = true;
33         Queue<Point> queue = new LinkedList<Point>();
34         Point newP = new Point(i, j);
35         queue.add(newP);
36         visited[i][j] = true;
37         points.add(newP);
38         int[] deltaX = {-1, 0, 1, 0};
39         int[] deltaY = {0, 1, 0, -1};
40
41         while(queue.isEmpty() == false){
42             Point curr = queue.poll();
43             for(int dir = 0; dir < 4; dir++){
44                 int x = curr.x + deltaX[dir];
45                 int y = curr.y + deltaY[dir];
46                 //if a ‘O‘ has out of bound neighbors, it means this ‘O‘ is not
47                 //surrounded.
48                 if(isValidPoint(board, x, y) == false){
49                     surrounded = false;
50                 }
51                 else if(board[x][y] == ‘O‘ && visited[x][y] == false){
52                     newP = new Point(x, y);
53                     queue.add(newP);
54                     visited[x][y] = true;
55                     points.add(newP);
56                 }
57             }
58         }
59         return surrounded;
60     }
61     private boolean isValidPoint(char[][] board, int i, int j){
62         return !(i < 0 || i >= board.length || j < 0 || j >= board[0].length);
63     }
64 }

Solution 2. BFS, O(n * m) runtime, with a better space complexity on average, still O(n * m) space for the queue used in bfs in the worst case

If a cell is ‘O‘ and not surrounded by ‘X‘, it means this cell must be connected via a bunch of other ‘O‘s to a ‘O‘ that is on the edge of the board.

Solution 1 starts from inside and try to hit the edge to determine if a group of connected Os are surrounded by X or not.

Instead, we can try to solve this problem in a reversed fashion. If we starts at Os at the edges and do bfs on connected Os toward the inside of the board,

we can find all connected Os that are NOT surrounded by X. The benefit of this reverse is that we can change the Os to Ws along the way to mark that

these cells are not surrounded by X. After we are done with all bfs, we do a final iteration of the board and change all Ws to Os and all non Ws to Xs.

This is correct since Os that are surround by X is not reachable from the edgy Os and will stay as Os after the bfs. Marking Ws on the fly also save

us from using an extra 2D array to track if a cell has been visited. A visited O will be changed to W and it will not be visited again.

 1 public class Solution {
 2     public void surroundedRegions(char[][] board) {
 3         if(board == null || board.length == 0 || board[0].length == 0) {
 4             return;
 5         }
 6         int n = board.length;
 7         int m = board[0].length;
 8         for(int i = 0; i < n; i++) {
 9             bfsFromEdgeOfBoard(board, i, 0);
10             bfsFromEdgeOfBoard(board, i, m - 1);
11         }
12         for(int j = 0; j < m; j++) {
13             bfsFromEdgeOfBoard(board, 0, j);
14             bfsFromEdgeOfBoard(board, n - 1, j);
15         }
16         for(int i = 0; i < n; i++) {
17             for(int j = 0; j < m; j++) {
18                 if(board[i][j] == ‘W‘) {
19                     board[i][j] = ‘O‘;
20                 }
21                 else {
22                     board[i][j] = ‘X‘;
23                 }
24             }
25         }
26     }
27     private void bfsFromEdgeOfBoard(char[][] board, int row, int col) {
28         if(board[row][col] != ‘O‘) {
29             return;
30         }
31         int[] deltaX = {-1, 0, 1, 0};
32         int[] deltaY = {0, 1, 0, -1};
33         Queue<Integer> qx = new LinkedList<Integer>();
34         Queue<Integer> qy = new LinkedList<Integer>();
35         qx.add(row);
36         qy.add(col);
37         board[row][col] = ‘W‘;
38
39         while(!qx.isEmpty()) {
40             int cx = qx.poll();
41             int cy = qy.poll();
42             for(int dir = 0; dir < 4; dir++) {
43                 int nx = cx + deltaX[dir];
44                 int ny = cy + deltaY[dir];
45                 if(isInBound(board, nx, ny) && board[nx][ny] == ‘O‘) {
46                     board[nx][ny] = ‘W‘;
47                     qx.add(nx);
48                     qy.add(ny);
49                 }
50             }
51         }
52     }
53     private boolean isInBound(char[][] board, int row, int col) {
54         return row >= 0 && row < board.length && col >= 0 && col < board[0].length;
55     }
56 }

Solution 3. Union Find, O(n * m) runntime, O(n * m) space

1. write a UnionFind class that supports finding root and connect roots at O(1) time.

2. for each unvisited O, connect its neighboring unvisited Os. Make sure when connecting roots, always make edge cells of O as the new root if possible.

3. after iterating the whole board at step 2, we get a balanced union find data structure that contains all cells. The O cells‘ roots are also updated to reflect if

they belong in the same union. Check each O cell to see if it has a edge cell O as its root, if it does, do nothing; if it does not, change it from O to X.

 1 public class Solution {
 2     private class UnionFind {
 3         private int[] father = null;
 4         private int row = 0;
 5         private int col = 0;
 6         public UnionFind(int n, int m){
 7             row = n;
 8             col = m;
 9             father = new int[n * m];
10             for(int i = 0; i < n * m; i++){
11                 father[i] = i;
12             }
13         }
14         public int find(int x){
15             if(father[x] == x){
16                 return x;
17             }
18             return father[x] = find(father[x]);
19         }
20         public void connect(int a, int b){
21             int root_a = find(a);
22             int root_b = find(b);
23             if(root_a != root_b){
24                 if(ifRootOnMatrixOutEdge(row, col, root_a) == true){
25                     father[root_b] = root_a;
26                 }
27                 else{
28                     father[root_a] = root_b;
29                 }
30             }
31         }
32     }
33     public void surroundedRegions(char[][] board) {
34         if(board == null || board.length == 0 || board[0].length == 0){
35             return;
36         }
37         int n = board.length;
38         int m = board[0].length;
39         UnionFind uf = new UnionFind(n, m);
40         boolean[][] visited = new boolean[n][m];
41         int[] deltaX = {-1, 0, 1, 0};
42         int[] deltaY = {0, 1, 0, -1};
43         for(int i = 0; i < n; i ++){
44             for(int j = 0; j < m; j++){
45                 if(board[i][j] == ‘O‘ && visited[i][j] == false){
46                     for(int dir = 0; dir < 4; dir++){
47                         int x = i + deltaX[dir];
48                         int y = j + deltaY[dir];
49                         if(isValidPoint(board, x, y) && board[x][y] == ‘O‘ &&
50                            visited[x][y] == false){
51                             uf.connect(i * m + j, x * m + y);
52                         }
53                     }
54                     visited[i][j] = true;
55                 }
56
57             }
58         }
59         for(int i = 0; i < n; i++){
60             for(int j = 0; j < m; j++){
61                 if(board[i][j] == ‘O‘ && !ifRootOnMatrixOutEdge(n, m, uf.find(i * m + j))){
62                     board[i][j] = ‘X‘;
63                 }
64             }
65         }
66     }
67     private boolean ifRootOnMatrixOutEdge(int rowNum, int colNum, int rootIdx){
68         return (rootIdx >= 0 && rootIdx <= colNum - 1
69                 || rootIdx >= (rowNum - 1) * colNum && rootIdx <= rowNum * colNum - 1
70                 || rootIdx % colNum == 0
71                 || rootIdx % colNum == colNum - 1);
72     }
73     private boolean isValidPoint(char[][] board, int i, int j){
74         return !(i < 0 || i >= board.length || j < 0 || j >= board[0].length);
75     }
76 }

Related Problems

Nearest Exit

Connecting Graph

Number of Islands II

Number of Islands

				
时间: 2024-08-28 08:26:41

[LintCode] Surrounded Regions的相关文章

[LintCode] Surrounded Regions 包围区域

Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O''s into 'X''s in that surrounded region.Example X X X XX O O XX X O XX O X X After capture all regions surrounded by 'X', the boar

LeetCode OJ - Surrounded Regions

我觉得这道题和传统的用动规或者贪心等算法的题目不同.按照题目的意思,就是将被'X'围绕的'O'区域找出来,然后覆盖成'X'. 那问题就变成两个子问题: 1. 找到'O'区域,可能有多个区域,每个区域'O'都是相连的: 2. 判断'O'区域是否是被'X'包围. 我采用树的宽度遍历的方法,找到每一个'O'区域,并为每个区域设置一个value值,为0或者1,1表示是被'X'包围,0则表示不是.是否被'X'包围就是看'O'区域的边界是否是在2D数组的边界上. 下面是具体的AC代码: class Boar

LeetCode: Surrounded Regions 解题报告

Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For example,X X X XX O O XX X O XX O X XAfter running your function, the

leetcode --day12 Surrounded Regions &amp; Sum Root to Leaf Numbers &amp; Longest Consecutive Sequence

1.  Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For example, X X X X X O O X X X O X X O X X After running your fu

[LeetCode][JavaScript]Surrounded Regions

Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For example, X X X X X O O X X X O X X O X X After running your function

【leetcode】Surrounded Regions

Surrounded Regions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For example, X X X X X O O X X X O X X O X X After running your function

【LeetCode】 Surrounded Regions (BFS &amp;&amp; DFS)

题目:Surrounded Regions 广搜和深搜都能解决,但是LeetCode上使用深搜时会栈溢出 DFS: <span style="font-size:18px;">/*LeetCode Surrounded Regions * 题目:给定一个字符数组,由'X'和'O'组成,找到所有被x包围的o并将其替换为x * 思路:只要替换被包围的o就行,如果有一个o是边界或者上下左右中有一个是o且这个o不会被替换,则该点也不会被替换 * 从四条边开始,因为在这4周的一定不是

Surrounded Regions LeetCode :My Solution

Surrounded Regions Total Accepted: 14948 Total Submissions: 105121My Submissions Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For exampl

LeetCode: Surrounded Regions [130]

[题目] Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured by flipping all 'O's into 'X's in that surrounded region. For example, X X X X X O O X X X O X X O X X After running your function, the board sh