Surrounded Regions (130)
1. BFS
时间 O(n*m)
空间 O(1)
1. 把所有的O标记为‘1’
2. 从四周向内看把标记为‘1’的变回'O' -> 时间O(n+m)
3. 把没有在2步骤中变化的‘1’变‘X’->时间O(n*m)
->时间O(n*m + n +m) 此方法比Union find要快
private int row; private int col; public void solve(char[][] board) { if(board == null || board.length == 0 || board[0].length == 0) return; row = board.length; col = board[0].length; for(int i = 0; i < row; i++) for(int j = 0; j < col; j++) if(board[i][j] == 'O') board[i][j] = '1'; for(int i = 0; i < row; i++){ dfs(board, i, 0); dfs(board, i, col - 1); } for(int j = 0; j < col; j++){ dfs(board, 0, j); dfs(board, row - 1, j); } for(int i = 0; i < row; i++) for(int j = 0; j < col; j++) if(board[i][j] == '1') board[i][j] = 'X'; return; } private void dfs(char[][] board, int x, int y){ if(x < 0 || y < 0 || x >= row || y >= col || board[x][y] != '1') return; board[x][y] = 'O'; int[] dx = {0,0,1,-1}; int[] dy = {1,-1,0,0}; for(int i = 0 ; i < 4; ++i){ dfs(board, x + dx[i], y + dy[i]); } }
2. union find
时间O(N*M)
空间O(n*m)
首先定义Unionfindclass. 注意这里用rank来提高效率
class UnionFind { int[] father; int[] rank; public UnionFind(int n){ father = new int[n]; rank = new int[n]; for(int i = 0 ; i < n; ++i){ father[i] = i; rank[i] = 1; } } public void union(int a , int b){ int father_a = find(a); int father_b = find(b); if(father_a!= father_b){ if(rank[father_a] > rank[father_b]){ father[father_b] = father_a; rank[father_a]++; }else{ father[father_a] = father_b; rank[father_b]++; } } } public int find(int a){ if(father[a] != a){ father[a] = find(father[a]); } return father[a]; } }
然后主程序调用
对于每一个O, 如果在边上就合并入dummy node所在union。
如果不在边上就合并入任意的O的集合。 这里再看四周四个是否为O并且合并。
最后处理完以后再次遍历,如果当前node和dummy node在同一个集合,就不要改变字符
-> 时间O(n*m *2)
public void solve(char[][] board) { if(board == null || board.length ==0 || board[0].length == 0) return; int n = board.length; int m = board[0].length; int dummyNode = n*m; UnionFind uf = new UnionFind(n*m +1); int[] dx = {0,0,1,-1}; int[] dy = {1,-1,0,0}; for(int i = 0; i < n; ++i){ for(int j = 0 ; j < m; ++j){ if(board[i][j] == 'X') continue; if(i== 0 || i == n-1 || j == 0 || j== m-1){ // this is on borader uf.union(getNode(m,i,j), dummyNode); continue; } for(int c = 0 ; c < 4; ++c){ if(board[i + dx[c]][j + dy[c]] == 'O') uf.union(getNode(m,i,j), getNode(m,i + dx[c], j + dy[c])); } } } for(int i = 1; i < n-1; ++i){ for(int j = 1 ; j < m-1; ++j){ if(board[i][j] == 'O' && uf.find(getNode(m,i,j)) != uf.find(dummyNode)){ board[i][j] = 'X'; } } } } private int getNode(int m, int i, int j){ return i*m+j; }