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:

11110
11010
11000
00000

Answer: 1

Example 2:

11000
11000
00100
00011

Answer: 3


题意:

给定一个由字符‘1’(岛屿)和字符‘0’(水)组成的二维网格地图,计算岛屿数量。一个岛屿由水平或者垂直相连的土地所形成,四周被水包围。可以假设网格地图四周都是被水包围着。


思路一:

DFS实现,轮训这个二维网格地图,当检测到一个节点的值为‘1’字符时,调用explore子函数所有该节点周围上下左右是否还有值为字符‘1’的网格,将检测过得格点复制为‘x’,表示检测过了。整个过程直到搜寻完周围所有格点之后,将返回值加1。

算法工作步骤如下:

1、扫描二维网格地图中的每个格点;

2、如果格点值是‘1’字符,则explore这个岛屿;

3、将已经检测过得岛屿格点标记为‘x’字符;

4、一旦完成一个岛屿的搜寻之后,将岛屿计数器加1.

代码:java版:5ms

public class Solution {
    static int[] dx = {-1, 0, 0, 1}; //搜寻一个格点上下左右时所需要的操作节点
    static int[] dy = {0, 1, -1, 0};
    public static int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0) return 0;
        int islands = 0;
        for (int i=0; i<grid.length; i++) { //扫描二维网格地图中的1字符
            for (int j=0; j<grid[i].length; j++) {
                if (grid[i][j] == '1') {
                    explore(grid, i, j); //搜索一个岛屿
                    islands++; //岛屿数加1
                }
            }
        }
        return islands;
    }
    public static void explore(char[][] grid, int i, int j) {
        grid[i][j] = 'x';
        for (int d=0; d<dx.length; d++) {
            if (i+dy[d]<grid.length && i+dy[d]>=0 && j+dx[d]<grid[0].length && j+dx[d]>=0 && grid[i+dy[d]][j+dx[d]]=='1')
                explore(grid,i+dy[d],j+dx[d]); //递归搜寻下一个节点周围的节点
        }
    }
}
另一种写法,使用一个visited的数组来记录该节点是否检测过,而不是修改原网格地图的值来实现。思路基本一致。

代码:C++版:16ms

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size(), res = 0;
        vector<vector<bool>> visited(m, vector<bool>(n, false));
        for (int i=0; i<m; i++) {
            for (int j=0; j<n; j++) {
                if (grid[i][j] == '1' && !visited[i][j]) {
                    dfs(grid, visited, i, j);
                    ++res;
                }
            }
        }
        return res;
    }
    void dfs(vector<vector<char>> &grid, vector<vector<bool>> &visited, int x, int y) {
        if (x < 0 || x >= grid.size()) return;
        if (y < 0 || y >= grid[0].size()) return;
        if (grid[x][y] != '1' || visited[x][y]) return;
        visited[x][y] = true;
        dfs(grid, visited, x-1, y);
        dfs(grid, visited, x+1, y);
        dfs(grid, visited, x, y-1);
        dfs(grid, visited, x, y+1);
    }
};

思路二:

BFS实现,借助队列queue实现BFS遍历,将每一个格点值为‘1’字符的格点放入队列中,针对于该节点的上下左右均进行检测扫描,如果等于字符1,则将检测到的格点也放入队列中,将检测过得格点值设置为‘0’字符,以防止多次检测到。

代码:C++版:24ms

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
         if(grid.size() == 0 || grid[0].size() == 0) return 0;
         int res = 0;
         for(int i = 0; i < grid.size(); ++ i) //扫描网格
             for(int j = 0; j < grid[0].size(); ++ j)
                 if(grid[i][j] == '1')
                 {
                     ++res;
                     BFS(grid, i, j);
                 }
         return res;
    }
private:
    void BFS(vector<vector<char>> &grid, int x, int y)
    {
         queue<vector<int>> q;
         q.push({x, y});
         grid[x][y] = '0';
         while(!q.empty())
         {
             x = q.front()[0], y = q.front()[1];
             q.pop();
             
             if(x > 0 && grid[x - 1][y] == '1') //前
             {
                 q.push({x - 1, y});
                 grid[x - 1][y] = '0';
             }
             if(x < grid.size() - 1 && grid[x + 1][y] == '1') //后
             {
                 q.push({x + 1, y});
                 grid[x + 1][y] = '0';
             }
             if(y > 0 && grid[x][y - 1] == '1') //下
             {
                 q.push({x, y - 1});
                 grid[x][y - 1] = '0';
             }
             if(y < grid[0].size() - 1 && grid[x][y + 1] == '1') //上
             {
                 q.push({x, y + 1});
                 grid[x][y + 1] = '0';
             }
         }
     }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值