LeetCode Medium|【200. 岛屿数量】

力扣题目链接
代码随想录文章链接
在代码随想录中写了深搜和广搜两个思路,并且它使用的是 ACM 模式。在这里,我们从 leetcode 的核心代码的角度来讲解核心思路。

首先我们分析题目,题目其实意思就是说,所有的连接起来的 “1” 表示一座岛屿,然后 0 是水流,其实我们最主要的逻辑就是:

  • 搜索整个网格,只要遇到没有访问过的陆地,马上结果 +1;
  • 我们要把相邻的陆地全部打上“已经访问” 的标记。
  • 随后我们继续开始搜索网格。

在基础的思路分析中,搜索网格的代码很简单,两个 for 循环,但是我们如何把相邻陆地都打上 “已访问” 标记呢?那就离不开我们的搜索算法来:DFS、BFS。

DFS

在这个代码中有一个小技巧:那就是把终止条件写在了调用 dfs 的地方:

private:
    int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 顺序为:右, 下, 左, 上(逆时针)

    void dfs(const vector<vector<char>>& grid
             , vector<vector<bool>>& visited
             , int x
             , int y) {
        for (int i = 0; i < 4; i++) {
            int nextx = x + dir[i][0];
            int nexty = y + dir[i][1];
            if (nextx < 0 || nextx >= grid.size() 
                || nexty < 0 || nexty >= grid[0].size()) 
                continue;
            if (!visited[nextx][nexty] && grid[nextx][nexty] == '1') {
                visited[nextx][nexty] = true;
                dfs(grid, visited, nextx, nexty);
            }
        }
    }

代码的核心流程如下:

        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (!visited[i][j] && grid[i][j] == '1') {
                    res++;
                    visited[i][j] = true;
                    dfs(grid, visited, i, j);
                }
            }
        }

BFS

广度优先搜索主打的就是一个 队列 + 迭代

这里需要注意的一个问题就是,只要加入队列,我们应该立即标记该节点已经走过。

int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 四个方向
void bfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {
    queue<pair<int, int>> que;
    que.push({x, y});
    visited[x][y] = true; // 只要加入队列,立刻标记
    while(!que.empty()) {
        pair<int ,int> cur = que.front(); que.pop();
        int curx = cur.first;
        int cury = cur.second;
        for (int i = 0; i < 4; i++) {
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1];
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 越界了,直接跳过
            if (!visited[nextx][nexty] && grid[nextx][nexty] == 1) {
                que.push({nextx, nexty});
                visited[nextx][nexty] = true; // 只要加入队列立刻标记
            }
        }
    }
}

你可能感兴趣的:(#,LeetCode,Medium,leetcode,深度优先,算法)