例题
给你一个大小为 m x n
的二进制矩阵 grid
,其中 0
表示一个海洋单元格、1
表示一个陆地单元格。
一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid
的边界。
返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。
深搜三部曲
1. 确认递归函数,参数
先弄清思路,深搜只是一个工具,在本题中,它用于遍历接壤的土地部分(遍历后把这些土地都标记为 ture:已访问过)。在主函数中,我们先统计飞地的数量,只有土地在边缘的时候才有可能飞出去,所以我们遍历数组的四边,将四边上的土地及其接壤地标为true。那么数组中剩下的没遍历的土地必定是飞不出去的,即题目所求。
递归函数自然是dfs函数及两个数组(grid/visited),以及现在的所在地x,y.
2. 确认终止条件
终止条件是深搜函数的终止条件,若当前遍历到的坐标不是土地 or 已被访问过,就可以退出了。
3. 处理目前搜索节点出发的路径
每遍历到一个结点,并确定不满足终止条件,我们搜索它的上下左右坐标,并继续从这些坐标深搜。
code
class Solution {
public:
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};//四个方向
int numEnclaves(vector<vector<int>>& grid) {
int count = 0;
int m = grid.size();
int n = grid[0].size();
vector<vector<bool>> visited(m,vector<bool>(n,false));
//若是有没访问过的陆地,这些陆地的接壤地皆是飞地,标为true
//从第一行开始
for(int j = 0; j < n; j++)
{
if(visited[0][j] == false && grid[0][j] == 1)
dfs(grid, visited, 0, j);
}
//从第一列开始
for(int i = 0; i < m; i++)
{
if(visited[i][0] == false && grid[i][0] == 1)
dfs(grid, visited, i, 0);
}
//从第m行开始
for(int j = 0; j < n; j++)
{
if(visited[m-1][j] == false && grid[m-1][j] == 1)
dfs(grid, visited, m-1, j);
}
//从第n列开始
for(int i = 0; i < m; i++)
{
if(visited[i][n-1] == false && grid[i][n-1] == 1)
dfs(grid, visited, i, n-1);
}
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
{
if(grid[i][j] == 1 && visited[i][j] == false)//是陆地且没访问过
count++;
}
return count;
}
//深搜
void dfs(vector<vector<int>>& grid,vector<vector<bool>>& visited,int x,int y)
{
// if()
// {
// ++;
// return ;
// }
if(grid[x][y] == 0 || visited[x][y] == true) return ;
visited[x][y] = true;
for(int i = 0; i < 4; i++)//遍历四个方向,把能走到陆地都标为true
{
int nextx = x + dir[i][0];
int nexty = y + dir[i][1];
if(nextx >=0 && nextx < grid.size() && nexty >=0 && nexty < grid[0].size())//若不出界
dfs(grid,visited,nextx,nexty);
}
return ;
}
};
广搜
待施工