思路:
广度优先遍历,将每一块的第一个1加入队列,然后往外扩散开,直到遇到水(0)
代码:
class Solution {
int row;
int col;
public int numIslands(char[][] grid) {
row=grid.length;
col=grid[0].length;
//四个方位
int[][] directions={{-1,0},{0,-1},{1,0},{0,1}};
//设置marked记录已走过,是boolean而不是Boolean
boolean[][] marked=new boolean[row][col];
int count=0;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
//没有被标记过且是陆地
if(!marked[i][j]&&grid[i][j]=='1'){
count++;
//设置一个队列存储搜索的值
LinkedList<int[]> queue=new LinkedList<>();
//把第一个位置放入队列,并标记已登录过
queue.addLast(new int[]{i,j});
marked[i][j]=true;
while(!queue.isEmpty()){
int[] cur=queue.removeFirst();
//四个方位搜寻
for(int k=0;k<4;k++){
int newX=curX+directions[k][0];
int newY=curY+directions[k][1];
//判断不越界、没被访问过、是陆地
if(inArea(newX,newY)&&!marked[newX][newY]&&grid[newX][newY]=='1'){
queue.addLast(new int[]{newRow,newCol});
//在入队列时就要置为true,不可在出队列时再操作
marked[newX][newY]=true;
}
}
}
}
}
}
return count;
}
private boolean inArea(int x,int y){
//注意=这些细节
return x>=0&&x<row&&y>=0&&y<col;
}
}
分解:
1)要记录是否访问过visited[][]
2)这里设置队列的存储类型为int[],这样就不需要每次入队前要进行x*col+y,以及出队后x=cur/col,y=cur%col的操作了
复杂度分析:
时间复杂度:O(M*N) M*N个元素都要遍历到(M行,N列)
空间复杂度:O(min(M,N)) 队列中最多存储M或N个元素