给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
示例 2:
输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3
该题有三种思路:1、DFS:深度优先遍历;2、广度优先遍历;3、并查集Union Find
思路一、DFS
从头开始遍历,碰到为1的元素,则进行记录result;代表着第几块大陆,然后递归遍历该元素上下左右的元素,如果值为1则使其归0,并且递归该元素的上下左右元素值是否为1,若为1接着归0...周而复始;直到超出边界或者找不到值为1的元素为止;看似复杂,其实只需递归即可。
代码:
public int numIslands(char[][] grid) {
if(grid == null || grid.length == 0)
{
return 0;
}
int row = grid.length;
int col = grid[0].length;
int result = 0;
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
if(grid[i][j] == '1')
{
result++;
dfs(grid,i,j,row,col);
}
}
}
return result;
}
public void dfs(char[][] grid,int x,int y,int row,int col)
{
if(x < 0 || y < 0||x>=row||y>=col)
{
return;
}
grid[x][y] = '0';
dfs(grid,x+1,y,row,col);
dfs(grid,x-1,y,row,col);
dfs(grid,x,y+1,row,col);
dfs(grid,x,y-1,row,col);
}
}
思路二、BFS
该思路与DFS思路相似,将值为1的元素下标压入队列,然后判断其上下左右元素值是否为1,若为1接着压入队列,最后遍历队列,将队列中存储的下标的值负值为1;
初始化队列:Queue<int[]> quene = new LinkedList<>();
操作:quene.add();队列添加元素
quene.poll();删除队顶元素并且弹出
代码:
public static int numIslands(char[][] grid) {
//BFS
if(grid == null || grid.length == 0)
{
return 0;
}
int row = grid.length;
int col = grid[0].length;
int result = 0;
//BFS一般都用队列进行辅助实现
Queue<int[]> quene = new LinkedList<>();
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
if(grid[i][j] == '1')
{
result++;
//如果将元素值为1,将下标存进队列
quene.add(new int[] {i,j});
grid[i][j] = '0';
//对队列进行遍历,直到队列为空,
while(!quene.isEmpty())
{
int[] cur = quene.poll();//将队列中存储的元素取出
int x = cur[0];
int y = cur[1];
//对此元素的上下左右进行遍历,如果符合条件,依旧存入队列
if(x-1>=0 && grid[x-1][y] == '1')
{
grid[x-1][y] = '0';
quene.add(new int[] {x-1,y});
}
if(x+1<row && grid[x+1][y] == '1')
{
grid[x+1][y] = '0';
quene.add(new int[] {x+1,y});
}
if(y-1>=0 && grid[x][y-1] == '1')
{
grid[x][y-1] = '0';
quene.add(new int[] {x,y-1});
}
if(y+1<col && grid[x][y+1] == '1')
{
grid[x][y+1] = '0';
quene.add(new int[] {x,y+1});
}
}
}
}
}
return result;
}
思路三、并查集:我也不太懂
代码:
public static int numIslands(char[][] grid)
{
if(grid == null || grid.length == 0)
{
return 0;
}
int row = grid.length;
int col = grid[0].length;
int waters = 0;//记录水域0的数量
UnionFind uf = new UnionFind(grid);
for (int i = 0; i < row; i++) {
for(int j = 0;j < col;j++)
{
if(grid[i][j] == '0')
{
waters++;
}else {
int[][] directions = new int[][] {{i-1,j},{i+1,j},{i,j-1},{i,j+1}};
for (int[] d : directions) {
int x = d[0];
int y = d[1];
if(x >= 0 && x < row && y >= 0&& y < col&&grid[x][y] == '1')
{
uf.union(x*col+y,i*col+j);
}
}
}
}
}
return uf.getCount()-waters;
}
}
//并查集类,模板
class UnionFind{
public int[] root = null;
public int count = 0 ;//记录岛屿的数量
public UnionFind(char[][] grid) {
int row = grid.length;
int col = grid[0].length;
count = row*col;
root = new int[count];
for(int i =0;i < root.length;i++)
{
root[i] = i;
}
}
public int find(int x)
{
if(x == root[x])
{
return x;
}else
{
root[x] = find(root[x]);
return root[x];
}
}
public void union(int x,int y)
{
int rootX = find(x);
int rootY = find(y);
if(rootX != rootY)
{
root[rootX] = rootY;
count --;
}
}
public int getCount()
{
return count;
}
}
想养一只猫。
浙公网安备 33010602011771号