给你一个由 '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;
	}
	
}
posted on 2021-02-01 13:22  东宁王孟川  阅读(148)  评论(0)    收藏  举报