image.png
image.png

思路

image.png
这里棕色代表陆地,蓝色代表海洋
image.png
从数组中第一个元素找起,此时其数值为1,所以找到了一个陆地,关键是将关联的陆地进行标记,这样在找下一个岛屿的过程中才不会重复
这个过程就是floodfill的过程
其实就是从初始点开始进行一次深度优先遍历
一旦找到相邻的而且是陆地并且没有标记过,则进行标记
image.png
依次可得
image.png
image.png
image.png
对于此此时第5个点都考虑过了,此时进行回退,一直到第一行第2个点,此时向下标记
image.png
image.png
image.png
image.png
此时标记完成,逐步退回到第一个点
对于多个岛屿
image.png
先标记上第一个岛屿,然后找到第一个没被标记的陆地,继续标记
image.png
image.png

image.png
这里的很多技术与上一节的很多方法都是一样的

code

  1. class Solution {
  2. private int[][] d = {{0,1},{1,0},{0,-1},{-1,0}};
  3. private int m,n;
  4. private boolean[][] visited;
  5. boolean inArea(int x,int y){
  6. return x>=0&&x<m&&y>=0&&y<n;
  7. }
  8. //从grid[x][y]的位置开始,进行floodfill 将相连的土地进行标记
  9. private void dfs(char[][] grid,int x,int y){
  10. //设为已经访问过
  11. visited[x][y]=true;
  12. //四个方向进行标记
  13. for(int i=0;i<4;i++){
  14. int newx = x + d[i][0];
  15. int newy = y + d[i][1];
  16. //如果新的土地位置合法并且没有被访问过 则对新的位置进行dfs
  17. if(inArea(newx,newy)&&!visited[newx][newy]&&grid[newx][newy]=='1')
  18. dfs(grid,newx,newy);
  19. }
  20. //如果都没有找到 则返回
  21. return;
  22. }
  23. public int numIslands(char[][] grid) {
  24. m = grid.length;
  25. //特殊条件判断
  26. if(m==0)
  27. return 0;
  28. n = grid[0].length;
  29. visited = new boolean[m][n];
  30. int res = 0;
  31. //遍历第一个没访问过的陆地
  32. for(int i=0;i<m;i++){
  33. for(int j=0;j<grid[i].length;j++){
  34. //找到一个新的岛屿
  35. if(grid[i][j]=='1'&&!visited[i][j]){
  36. res++;
  37. dfs(grid,i,j); //进行floodfill标记 将同属于同一块岛屿的陆地设为已经访问过
  38. }
  39. }
  40. }
  41. return res;
  42. }
  43. }