[LeetCode] 200. Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:

Input:
11110
11010
11000
00000

Output: 1

Example 2:

Input:
11000
11000
00100
00011

Output: 3

这道题可以用宽度优先搜索,深度优先搜索,甚至并查集来做。我选了宽度优先搜索,这个比较简单直接。时间复杂度是O(M * N), 空间复杂度是O(min(M,N))。一般情况下,如果一个东西需要分层,可以考虑宽度优先搜索。这道题就是先找到一个是1的点,然后一层一层找下去,一直找到1的边界,然后这个island就找完了,count加一。分层的探索就是bfs。注意的是每一次把一个点加入queue的时候,一定要把这个点变成0,即这个点已经visit过了。

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        if not grid or not grid[0]:
            return 0

        m, n = len(grid), len(grid[0])
        count = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    self.bfs(grid, i, j)
                    count += 1
        return count
    
    def bfs(self, grid, r, c):
        queue = collections.deque()
        queue.append((r, c))
        grid[r][c] = '0'
        while queue:
            directions = [(0,1), (0,-1), (-1,0), (1,0)]
            r, c = queue.popleft()
            for d in directions:
                nr, nc = r + d[0], c + d[1]    
                if self.is_valid(grid, nr, nc) and grid[nr][nc] == '1':
                    queue.append((nr, nc))
                    grid[nr][nc] = '0'
     
    def is_valid(self, grid, r, c):
        m, n = len(grid), len(grid[0])
        return r >= 0 and r < m and c >= 0 and c < n

lintcode上有一道差不多的题,我曾经写过一个java version,但是这个vesion在pull的时候把点设置为visit过的,实际上不如在加入queue的时候转化,因为会重复。

public class Solution {
    /**
     * @param grid a boolean 2D matrix
     * @return an integer
     */
    class Coordinate {
        int x;
        int y;
        public Coordinate (int x, int y) {
            this.x = x;
            this.y = y;
        } 
        
    }
    public int numIslands(boolean[][] grid) {
        // Write your code here
        if (grid == null || grid.length == 0 || grid[0] == null || grid[0].length == 0) {
            return 0;
        }
        int count = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j]) {
                    markEdge(grid, i, j);
                    count++;
                }
            }
        }
        return count;
    }
    
    private void markEdge(boolean[][] grid, int x, int y) {
        int[] directX = {0, -1, 1, 0};
        int[] directY = {-1, 0, 0, 1};
        int nRow = grid.length;
        int nCol = grid[0].length;
        Coordinate original = new Coordinate(x, y);
        Queue<Coordinate> q = new LinkedList<Coordinate>();
        q.offer(original);
        while (!q.isEmpty()) {
            Coordinate node = q.poll();
            grid[node.x][node.y] = false; // This means this point has been checked. Since they belong to one queue, mark them as false means we don't have to make the count++ except the first time (in the main function, if is not satisified)
            for (int i = 0; i < directX.length; i++) {
                Coordinate neighbor = new Coordinate(node.x + directX[i], node.y + directY[i]);
                //System.out.println(neighbor.x + " " + neighbor.y);
                if (isInBound(neighbor, nRow, nCol) && grid[neighbor.x][neighbor.y]) {
                    q.offer(neighbor);    
                }
            }
        }
    }
    
    private boolean isInBound(Coordinate node, int row, int col) {
        int x = node.x;
        int y = node.y;
        return x >= 0 && x < row && y >= 0 && y < col; 
    }
}```

posted on 2020-04-18 05:08  codingEskimo  阅读(314)  评论(0编辑  收藏  举报

导航