⭐算法入门⭐《深度优先搜索》中等01 —— LeetCode 695. 岛屿的最大面积

🙉饭不食,水不饮,题必须刷🙉

C语言免费动漫教程,和我一起打卡!
🌞《光天化日学C语言》🌞

LeetCode 太难?先看简单题!
🧡《C语言入门100例》🧡

数据结构难?不存在的!
🌳《数据结构入门》🌳

LeetCode 太简单?算法学起来!
🌌《夜深人静写算法》🌌

一、题目

1、题目描述

  给定一个包含了一些 0 和 1 的非空二维数组 g r i d grid grid 。一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 g r i d grid grid 的四个边缘都被 0(代表水)包围着。找到给定的二维数组中最大的岛屿面积。
  样例输入1: [ [ 1 , 0 , 1 ] , [ 1 , 1 , 1 ] , [ 0 , 0 , 1 ] ] [[1,0,1],[1,1,1],[0,0,1]] [[1,0,1],[1,1,1],[0,0,1]]
  样例输出1: 6 6 6
  
  样例输入2: [ [ 1 , 0 , 1 ] , [ 0 , 1 , 0 ] , [ 0 , 0 , 1 ] ] [[1,0,1],[0,1,0],[0,0,1]] [[1,0,1],[0,1,0],[0,0,1]]
  样例输出2: 1 1 1

2、基础框架

  • c++ 版本给出的基础框架代码如下,定义一个函数maxAreaOfIsland,函数的参数是一个vector的嵌套,代表的是一个二维数组;
  • vector<vector<int>>可以理解成vector<T>,其中T代表vector的元素,并且这个元素是另一个vector<int>。当然,可以嵌套的实现三维数组,甚至更高维的数组。
class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
    }
};

3、原题链接

LeetCode 695. 岛屿的最大面积

二、解题报告

1、思路分析

  • g r i d grid grid 中的每个 1 抽象成一个节点,且都有一个唯一编号。两个水平或者垂直方向相邻且都为 1,则在这两个节点之间连接一条无向边。举个例子:
  • [ 1 0 0 1 1 1 0 1 0 1 1 1 ] \left[ \begin{matrix} 1 & 0 & 0 & 1 \\ 1 & 1 & 0 & 1 \\ 0 & 1 & 1 & 1 \end{matrix} \right] 110011001111
  • 先将每个 1 的位置都分配一个编号,假设行号为 i i i,列号为 j j j,则它的编号就是 i × 4 + j i \times 4 + j i×4+j,其中 4 4 4 代表总共有多少列。如下:
  • [ 0 E E 3 4 5 E 7 E 9 10 11 ] \left[ \begin{matrix} 0 & E & E & 3 \\ 4 & 5 & E & 7 \\ E & 9 & 10 & 11 \end{matrix} \right] 04EE59EE103711
  • E E E 的含义是 Empty 的意思,可以用一个额外的编号(不和其它现有编号冲突)表示,比如 -1。
  • 所以,它其实应该是这样一个图:
  • 这样,我们就可以转换成用深度优先搜索来求连通块问题了。
  • 关于深度优先搜索的更深入内容,可以参考这篇文章:夜深人静写算法(一)- 搜索入门

2、时间复杂度

  • 由于有哈希数组在,所以 g r i d grid grid 的每个元素最多被访问一次,如果长 n n n 宽为 m m m g r i d grid grid,时间复杂度为 O ( n m ) O(nm) O(nm)

3、代码详解

const int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };           // (1)
int bHash[100][100];                                                  // (2)
int n, m;                                                             // (3)

class Solution {
public:
    void dfs(vector<vector<int>>& grid, int &count, int x, int y) {   // (4)
        if(x < 0 || y < 0 || x >= n || y >= m) {
            return ;                                                  // (5)
        }
        if(!grid[x][y]) {
            return ;                                                  // (6)
        }

        if(bHash[x][y]) {
            return;                                                   // (7)
        }
        bHash[x][y] = 1;
        ++count;

        for(int i = 0; i < 4; ++i) {
            dfs(grid, count, x + dir[i][0], y + dir[i][1]);           // (8)
        }
    }

    int maxAreaOfIsland(vector<vector<int>>& grid) {
        n = grid.size();
        m = grid[0].size();
        memset(bHash, 0, sizeof(bHash));

        int count = 0, maxv = 0;
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < m; ++j) {
                if(grid[i][j] && !bHash[i][j]) {                      // (9)
                        count = 0;
                        dfs(grid, count, i, j);
                        maxv = max(maxv, count);                      // (10)
                    }
                }
            }
        }
        return maxv;
    }
};
  • ( 1 ) (1) (1) 代表四个方向的全局向量;
  • ( 2 ) (2) (2) 二维的哈希数组,用来标记一个位置有没有被访问过;
  • ( 3 ) (3) (3) 全局缓存 g r i d grid grid 的宽 和 高;
  • ( 4 ) (4) (4) 用于对全局进行搜素的递归函数,grid作为引用传参提高效率,count作为引用传参是当全局变量来用的,x,y代表的是当前枚举到的 行 和 列。
  • ( 5 ) (5) (5) 如果遇到搜索到边界的情况,终止搜索;
  • ( 6 ) (6) (6) 如果遇到不是岛屿的情况,终止搜索;
  • ( 7 ) (7) (7) 如果遇到已经搜索过的岛屿,终止搜索;否则,标记(x,y)被搜索过,且计数器count自增。
  • ( 8 ) (8) (8) 继续枚举四方向的下一个位置;
  • ( 9 ) (9) (9) grid的每个位置未被访问过(!bHash[i][j])的岛屿(grid[i][j])都必须枚举到;
  • ( 10 ) (10) (10) 取最大的连通块,max为系统库函数;

三、本题小知识

利用深度优先搜索,可以用来求图的连通块问题。


  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值