1. 题⽬链接:1020.⻜地的数量
2. 题⽬描述:
3. 解法:
算法思路:
正难则反:
从边上的1 开始搜索,把与边上1 相连的联通区域全部标记⼀下;然后再遍历⼀遍矩阵,看看哪些位置的1 没有被标记即可 标记的时候,可以⽤「多源bfs 」解决。
C++算法代码:
class Solution
{
public:
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int numEnclaves(vector<vector<int>>& grid)
{
int count=0;
int m=grid.size(),n=grid[0].size();
vector<vector<int>>answer(m,vector<int>(n,-1)); //答案
queue<pair<int,int>>q;
//第一行+最后一行
for(int i=0;i<n;i++)
{
if(answer[0][i]==-1&&grid[0][i]==1)
{
answer[0][i]=1;
q.push({0,i});
}
if(answer[m-1][i]==-1&&grid[m-1][i]==1)
{
answer[m-1][i]=1;
q.push({m-1,i});
}
}
//第一列+最后一列
for(int i=0;i<m;i++)
{
if(answer[i][0]==-1&&grid[i][0]==1)
{
answer[i][0]=1;
q.push({i,0});
}
if(answer[i][n-1]==-1&&grid[i][n-1]==1)
{
answer[i][n-1]=1;
q.push({i,n-1});
}
}
//多节点同时拓展
while(q.size())
{
int lenth=q.size();
for(int i=0;i<lenth;i++)
{
auto[a,b]=q.front();
q.pop();
for(int j=0;j<4;j++)
{
int x=a+dx[j],y=b+dy[j];
if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==1&&answer[x][y]==-1)
{
answer[x][y]=1;
q.push({x,y});
}
}
}
}
//计算剩余陆地个数
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(answer[i][j]==-1&&grid[i][j]==1)
{
count++;
}
}
}
return count;
}
};
Java算法代码:
class Solution
{
int[] dx = { 0, 0, 1, -1 };
int[] dy = { 1, -1, 0, 0 };
1
2
3
4
5 public int numEnclaves(int[][] grid)
{
int m = grid.length, n = grid[0].length;
boolean[][] vis = new boolean[m][n];
Queue<int[]> q = new LinkedList<>();
// 1. 把边上的 1 全部加⼊到队列中
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (i == 0 || i == m - 1 || j == 0 || j == n - 1)
{
if (grid[i][j] == 1)
{
q.add(new int[] {i, j});
vis[i][j] = true;
}
}
// 2. 多源 bfs
while (!q.isEmpty())
{
int[] t = q.poll();
int a = t[0], b = t[1];
for (int i = 0; i < 4; i++)
{
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 &&
!vis[x][y])
{
q.add(new int[] {x, y});
vis[x][y] = true;
}
}
}
// 3. 提取结果
int ret = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (grid[i][j] == 1 && !vis[i][j])
ret++;
return ret;
}
}