这篇题解写得非常好,值得反复看 https://leetcode-cn.com/problems/number-of-islands/solution/dao-yu-lei-wen-ti-de-tong-yong-jie-fa-dfs-bian-li-/
思路一:dfs深度遍历
代码如下:
答题模板
class Solution {
public int numIslands(char[][] grid) {
int result=0;
for(int i=0;i<grid.length;i++)
{
for(int j=0;j<grid[0].length;j++)
{
if(grid[i][j]=='1')
{
dfs(grid,i,j);
//当返回时,所有相连的岛屿“面积” '1'都被填充'2';
result+=1;
}
}
}
return result;
}
private void dfs(char[][] grid,int row,int column)
{
//越界
if(row<0 || column<0 || row>=grid.length || column>=grid[0].length)
return;
//不是岛屿
if(grid[row][column]!='1')
return;
grid[row][column]='2';
//遍历岛屿的上下左右节点
dfs(grid,row+1,column);
dfs(grid,row-1,column);
dfs(grid,row,column+1);
dfs(grid,row,column-1);
}
}
这道题属于dfs+遍历,并且深度为上下左右,遍历所有节点
为什么不是下和右呢?之前的都遍历过了,如果湖是工字岛,那么工字左下角无法作为一个岛屿的一部分,而是变成两个岛屿
原题解还讲了为什么置2不置0的其它细节
第二次写5分钟
思路二:bfs广度优先(借助队列)
主循环和dfs一致,一样需要遍历每个节点,不同的是处理方式,dfs是每次不断的往下深入直到碰见“0”,bfs是每次遍历每个节点的“周围”,while控制
class Solution {
public int numIslands(char[][] grid) {
if(grid==null||grid[0].length==0)
return 0;
int result=0;
for(int i=0;i<grid.length;i++)
{
for(int j=0;j<grid[0].length;j++)
{
if(grid[i][j]=='1')
{
bfs(grid,i,j);
result++;
}
}
}
return result;
}
private void bfs(char[][] grid,int row,int col)
{
Queue<int[]> queue=new LinkedList<>();
queue.add(new int[]{row,col});
while(!queue.isEmpty())//外循环控制“下一圈”
{
int len=queue.size();
while(len>0)//内循环控制“这一圈”
{
int[] temp=queue.poll();
row=temp[0];
col=temp[1];
//越界判断,以及现节点是否是岛屿的一部分,是才将其周围节点放入队列
if(row>=0 && col>=0 && row<grid.length && col<grid[0].length && grid[row][col]=='1')
{
grid[row][col]='2';
queue.add(new int[]{row+1,col});
queue.add(new int[]{row-1,col});
queue.add(new int[]{row,col+1});
queue.add(new int[]{row,col-1});
}
len--;
}
}
}
}
上面这个双重while是bfs,下面这个写法更像遍历
class Solution {
public int numIslands(char[][] grid) {
if(grid==null||grid[0].length==0)
return 0;
int result=0;
for(int i=0;i<grid.length;i++)
{
for(int j=0;j<grid[0].length;j++)
{
if(grid[i][j]=='1')
{
bfs(grid,i,j);
result++;
}
}
}
return result;
}
private void bfs(char[][] grid,int row,int col)
{
Queue<int[]> queue=new LinkedList<>();
queue.add(new int[]{row,col});
while(!queue.isEmpty())
{
int[] temp=queue.poll();
row=temp[0];
col=temp[1];
if(row>=0 && col>=0 && row<grid.length && col<grid[0].length && grid[row][col]=='1')
{
grid[row][col]='2';
queue.add(new int[]{row+1,col});
queue.add(new int[]{row-1,col});
queue.add(new int[]{row,col+1});
queue.add(new int[]{row,col-1});
}
}
}
}
时间复杂度 O(m*n)
空间复杂度 O(m>n?m:n)对角线 队列长度
第二次写,bfs要注意细节,以及队列存的是坐标
第三次写,bfs 节点遍历,借助队列,"下一圈"什么时候入队,判断节点是否越界,有一些细节问题