算法入门 05深度优先搜索(中等 - 第一题)LeetCode 695
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法入门 05深度优先搜索(中等 - 第一题)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]],输出 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]],输出 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、原题链接
二、解题报告
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
为系统库函数;
三、本题小知识
利用深度优先搜索,可以用来求图的连通块问题。
以上是关于算法入门 05深度优先搜索(中等 - 第一题)LeetCode 695的主要内容,如果未能解决你的问题,请参考以下文章
算法入门广度优先搜索(中等 - 第一题)LeetCode 994
算法入门深度优先搜索(中等 - 第二题)LeetCode 46