DFS和BFS的经典用法. 梦开始的地方. YYDS.
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
| class Solution { public int numIslands(char[][] grid) { Queue<int[]> q = new LinkedList<>(); int ans = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == '1') { grid[i][j] = '0'; q.offer(new int[] { i, j }); clearIsland(i, j, grid, q); ans += 1; } } } return ans; }
private void clearIsland(int row, int col, char[][] grid, Queue<int[]> q) { int[][] directions = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; while (!q.isEmpty()) { int[] pos = q.poll(); for (int[] direction : directions) { int neighborRow = pos[0] + direction[0]; int neighborCol = pos[1] + direction[1]; if (!isOutOfBound(grid, neighborRow, neighborCol) && grid[neighborRow][neighborCol] == '1') { grid[neighborRow][neighborCol] = '0'; q.offer(new int[] { neighborRow, neighborCol }); } } } }
private boolean isOutOfBound(char[][] grid, int row, int col) { return row < 0 || row >= grid.length || col < 0 || col >= grid[0].length; } }
|
BFS的方法. 很直接.
时间复杂度: O(M * N)
空间复杂度: O(min(M, N))
BFS的扩展规律, 假设一个无限大的matrix, 全部是1. 我们随便挑一个点, 开始扩散. 第一圈扩散是感染四个(2 * 2矩阵的外围). 第二次感染是8个(3 * 3矩阵外围), 第四次是12个. 第n次是4n - 4个. 这个通项公式4n - 4要求n >= 2. 假设是有边界的, 那么能扩展多少次呢? 看长和宽哪个小. 小的那个先被触碰到. 假设小的那个是m. 那么扩散的次数就是m / 2个. 此时当扩散到边界的时候, 这一圈感染的个数是: 4*(m / 2) - 4 = 2m - 4. 那么O一下就是O(m)了, 也就是O(min(m ,n)).
也有人说可能是max(m, n) 看这样一个例子:
0 1 1 0
1 1 1 1
1 1 1 1
在某个时候, queue中会有4个元素出现. 首先是(0, 1), (1, 0)和(1, 1)被推入queue. 然后(1, 0)出queue, 此时queue的长度变为2. 然后添加(1, 0)的neighbors: (2, 0)进入queue, (1, 1)在queue里面就不添加, 此时长度为3. 然后(1, 1)出queue, 长度变为2, 然后再把(1, 1)的neighors添加进来: (1, 2)和(2, 1), 此时queue长度变为4. 因此感觉是max(m, n). 但至于为什么m和n会限制queue中的elements的数量. 还要再思考一下.
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
| class Solution { public int numIslands(char[][] grid) { int ans = 0; for (int row = 0; row < grid.length; row++) { for (int col = 0; col < grid[0].length; col++) { if (grid[row][col] == '1') { helper(grid, row, col); ans += 1; } } } return ans; }
private void helper(char[][] grid, int row, int col) { grid[row][col] = '0'; int[][] directions = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; for (int[] direction : directions) { int newRow = row + direction[0]; int newCol = col + direction[1]; if (!isOutOfBound(grid, newRow, newCol) && grid[newRow][newCol] == '1') { helper(grid, newRow, newCol); } } }
private boolean isOutOfBound(char[][] grid, int row, int col) { return row < 0 || row >= grid.length || col < 0 || col >= grid[0].length; } }
|
DFS解法. 为了防止走向走过的格子, 走到一个格子就标记为0.
时间复杂度: O(M * N) 加入全部是‘1’. 从左上角开始向下到底, 右移一格然后向上, 这样走s型路线.
空间复杂度: O(M * N) 也是全是‘1’, 走s型路线.