给你一个 m x n 的矩阵 grid 和一个正整数 k。一个 岛屿 是由 正 整数(表示陆地)组成的,并且陆地间 四周连通(水平或垂直)。
一个岛屿的总价值是该岛屿中所有单元格的值之和。
返回总价值可以被 k 整除的岛屿数量。
示例 1:

输入: grid = \[0,2,1,0,0,0,5,0,0,5,0,0,1,0,0,0,1,4,7,0,0,2,0,0,8], k = 5
输出: 2
解释:
网格中包含四个岛屿。蓝色高亮显示的岛屿的总价值可以被 5 整除,而红色高亮显示的岛屿则不能。
示例 2:

输入: grid = \[3,0,3,0, 0,3,0,3, 3,0,3,0], k = 3
输出: 6
解释:
网格中包含六个岛屿,每个岛屿的总价值都可以被 3 整除。
提示:
m == grid.lengthn == grid[i].length1 <= m, n <= 10001 <= m * n <= 10^50 <= grid[i][j] <= 10^61 <= k < = 10^6
分析:将每个陆地单元格看作一个节点,上下左右相邻的陆地之间存在一条边,则每座岛屿对应图中的一个连通块。可以使用广度优先搜索,遍历每座岛屿中的所有陆地,计算其总价值,并判断总价值是否可以被 (k) 整除。
使用二维数组 flag 记录每个单元格是否已经访问,并依次枚举网格中的所有单元格。对于尚未访问的陆地单元格 (i,j),从该位置开始一次广度优先搜索:
-
将 (i,j) 标记为已访问并加入队列,将当前岛屿的总价值
cnt初始化为grid[i][j]。 -
不断取出队首单元格,检查其上下左右四个相邻位置。若相邻位置位于网格内、属于陆地且尚未访问,则将其标记为已访问,累加其价值,并加入队列。
-
当队列为空时,当前岛屿遍历完毕。若
cnt % k == 0,则将答案加一。
注意总价值可能超出 int 型变量最大值。
每次搜索恰好遍历一座完整岛屿,而已访问的陆地不会再次触发搜索,因此每座岛屿都会被统计一次。最终返回满足条件的岛屿数量即可。
cpp
class Solution {
public:
int countIslands(vector<vector<int>>& grid, int k) {
int n=grid.size(),m=grid[0].size(),ans=0;
int flag[n][m];
int dir_x[]={-1,1,0,0};
int dir_y[]={0,0,-1,1};
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
flag[i][j]=0;
for(int i=0;i<n;++i)
{
for(int j=0;j<m;++j)
{
if(grid[i][j]==0)flag[i][j]=1;
else if(!flag[i][j])
{
long long cnt=grid[i][j];flag[i][j]=1;
queue<pair<int,int>>que;que.push({i,j});
while(!que.empty())
{
int xx=que.front().first,yy=que.front().second;que.pop();
for(int k=0;k<4;++k)
{
int x=xx+dir_x[k],y=yy+dir_y[k];
if(x<0||x==n||y<0||y==m||flag[x][y]||!grid[x][y])continue;
flag[x][y]=1,cnt+=grid[x][y],que.push({x,y});
}
}
if(cnt%(1LL*k)==0)ans++;
}
}
}
return ans;
}
};