力扣刷题---岛屿问题--c++

DFS:深度优先遍历:深度优先遍历是一种优先走到底、无路可走再回头的遍历方式

我们所熟悉的 DFS(深度优先搜索)问题通常是在树或者图结构上进行的。而我们今天要讨论的 DFS 问题,是在一种「网格」结构中进行的。岛屿问题是这类网格 DFS 问题的典型代表。网格结构遍历起来要比二叉树复杂一些,如果没有掌握一定的方法,DFS 代码容易写得冗长繁杂。

网格类问题的 DFS 遍历方法

网格问题的基本概念:
我们首先明确一下岛屿问题中的网格结构是如何定义的,以方便我们后面的讨论。

网格问题是由 m×n 个小方格组成一个网格,每个小方格与其上下左右四个方格认为是相邻的,要在这样的网格上进行某种搜索。

岛屿问题是一类典型的网格问题。每个格子中的数字可能是 0 或者 1。我们把数字为 0 的格子看成海洋格子,数字为 1 的格子看成陆地格子,这样相邻的陆地格子就连接成一个岛屿。

在这样一个设定下,就出现了各种岛屿问题的变种,包括岛屿的数量、面积、周长等。不过这些问题,基本都可以用 DFS 遍历来解决。

DFS遍历基本框架:

1.跳出条件

2.遍历方向

类比树的DFS遍历,树:跳出条件--》root==null;遍历方向---》左右孩子

void dfs(TreeNode*root) {
    //边界条件
    if (!root) {
        return;
    }
    // 访问两个相邻结点:左子结点、右子结点
    dfs(root->left);
    dfs(root->right);
}

由此我们可以推出网格的dfs遍历:跳出条件:数组下标越界;遍历方向:上下左右

注意当 r == grid.size()时,是越界! 

但访问过得节点肯定不能再次访问了,那如何标记呢?可以直接将值变为2(区别于0,1)

于是有了三种情况

  • 0 —— 海洋
  • 1 —— 陆地(未遍历过)
  • 2 —— 陆地(已遍历过)
void dfs(vector<vector<int>>& grid, int r, int c) {
    // 判断 base case
    if (!inArea(grid, r, c)) {
        return;
    }
    // 如果这个格子不是岛屿,直接返回
    if (grid[r][c] != 1) {
        return;
    }
    grid[r][c] = 2; // 将格子标记为「已遍历过」
    
    // 访问上、下、左、右四个相邻结点
    dfs(grid, r - 1, c);
    dfs(grid, r + 1, c);
    dfs(grid, r, c - 1);
    dfs(grid, r, c + 1);
}

// 判断坐标 (r, c) 是否在网格中
bool inArea(vector<vector<int>>& grid, int r, int c) {
    return 0 <= r && r < grid.size() 
        && 0 <= c && c < grid[0].size();
}

说回本题:判断岛屿的个数:其实可以理解为能进行几次DFS。(进行一次深度遍历,将本块岛屿的所有小岛全部标记)

由此得到本题代码:

注意本题vetor类型为char;上面解释里面写的为int类型。

class Solution {
public:
    void dfs(vector<vector<char>>& grid, int r, int c) {
        // 判断 base case
        if (!inArea(grid, r, c)) {
            return;
        }
        // 如果这个格子不是岛屿,直接返回
        if (grid[r][c] != '1') {
            return;
        }
        grid[r][c] = 2; // 将格子标记为「已遍历过」

        // 访问上、下、左、右四个相邻结点
        dfs(grid, r - 1, c);
        dfs(grid, r + 1, c);
        dfs(grid, r, c - 1);
        dfs(grid, r, c + 1);
    }

    // 判断坐标 (r, c) 是否在网格中
    bool inArea(vector<vector<char>>& grid, int r, int c) {
        return 0 <= r && r < grid.size() && 0 <= c && c < grid[0].size();
    }

    int numIslands(vector<vector<char>>& grid) {
        int ans = 0;
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] == '1') {//找到一块未标记的岛屿
                    ans++;//数量+1
                    dfs(grid, i, j);//迅速占领
                }
            }
        }
        return ans;
    }
};

再来一道

463. 岛屿的周长

什么情况下周长增加:1.这个边是海和岛的分界线 2.边是临界边(网格的头)

if(gird[i][j]==0) return 1;
if(!inarea[i][j]) return 1;
if(grid[i][j]==2) return 0;

所以完整代码:

class Solution {
public:
    int dfs(vector<vector<int>>& grid, int row, int col) {
        if (!inarea(grid, row, col))
            return 1;
        if (grid[row][col] == 0)
            return 1;
        if (grid[row][col] != 1)
            return 0;
        grid[row][col] = 2;

        return dfs(grid, row + 1, col) + dfs(grid, row - 1, col) +
               dfs(grid, row, col + 1) + dfs(grid, row, col - 1);
    }

    bool inarea(vector<vector<int>>& grid, int row, int col) {
        if (row < 0 || row >=grid.size())
            return false;
        if (col < 0 || col >=grid[0].size())
            return false;
        return true;
    }
    int islandPerimeter(vector<vector<int>>& grid) {
        int ans = 0;
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] == 1)
                    ans += dfs(grid, i, j);
            }
        }
        return ans;
    }
};

再来一道: 

695. 岛屿的最大面积

题目简单清晰明了,岛屿的面积是岛上值为 1 的单元格的数目。所以只需要返回

最大的值为 1 的单元格数目之和就可以啦。

class Solution {
public:
    int max_ans = 0;
    int ans = 0;
    void dfs(vector<vector<int>>& grid, int row, int col) {
        if (!inarea(grid, row, col))
            return;
        if (grid[row][col] == 0 || grid[row][col] == 2)
            return;
        ans += 1;
        grid[row][col] = 2;
        // 访问上、下、左、右四个相邻结点
        dfs(grid, row - 1, col);
        dfs(grid, row + 1, col);
        dfs(grid, row, col - 1);
        dfs(grid, row, col + 1);
    }
    bool inarea(vector<vector<int>>& grid, int row, int col) {
        if (row < 0 || row >= grid.size())
            return false;
        if (col < 0 || col >= grid[0].size())
            return false;
        return true;
    }
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] == 1) {
                    ans=0;
                    dfs(grid, i, j);
                    max_ans = max(ans, max_ans);
                }
            }
        }
        return max_ans;
    }
};

好了,以上就结束了,另外,强烈建议看看参考链接,太6了。

参考链接:. 岛屿问题- 力扣(LeetCode)

相关推荐

  1. C语言】【小白的疑问

    2024-03-18 21:32:01       29 阅读
  2. 笔记(1)两数之和(C++)

    2024-03-18 21:32:01       12 阅读
  3. 200. 岛屿数量

    2024-03-18 21:32:01       37 阅读
  4. -290.单词规律

    2024-03-18 21:32:01       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-18 21:32:01       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-18 21:32:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-18 21:32:01       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-18 21:32:01       20 阅读

热门阅读

  1. 【C#语言入门】19. 什么是类

    2024-03-18 21:32:01       21 阅读
  2. 使用TOPDN做L53免费域名DNS解析方法

    2024-03-18 21:32:01       23 阅读
  3. Rust矢量数据库领域的优势

    2024-03-18 21:32:01       21 阅读
  4. 【Python学习笔记】Python logging模块的学习

    2024-03-18 21:32:01       25 阅读
  5. 算法笔记p142快速排序

    2024-03-18 21:32:01       22 阅读
  6. docker服务起不来原因及解决

    2024-03-18 21:32:01       21 阅读
  7. JDBC的概念

    2024-03-18 21:32:01       23 阅读
  8. pyttsx3应用场景案例

    2024-03-18 21:32:01       18 阅读