【DFS解决floodfill算法】岛屿数量

文章摘要:

  • 题目要求在给定的二维矩阵中,统计由相邻陆地('1')组成的岛屿数量,其中相邻指水平或垂直方向相连。通过深度优先搜索(DFS)解决:遍历矩阵,每发现未被访问的陆地时标记为已访问并计数,然后递归搜索其四周相邻陆地。全局变量记录矩阵信息及访问状态,方向数组简化四向搜索。无需回溯或剪枝,当所有陆地访问完毕即返回岛屿总数。代码实现中,主函数初始化并遍历矩阵,DFS函数处理相邻陆地标记,确保每个岛屿只统计一次。

文章目录

题目链接:200. 岛屿数量

一、题目解析

题目给我们一个由 1(陆地)0(水) 组成的的二维网格 grid,我们需要计算网格中岛屿的数量

岛屿总是被水包围,并且每座岛屿只能由水平方向 和/或竖直方向相邻的陆地连接形成。

示例1,题目给出的二维网格 grid 是:

1 1 1 1 0
1 1 0 1 0
1 1 0 0 0
0 0 0 0 0

那么岛屿只有一块:

1 1 1 1 0
1 1 0 1 0
1 1 0 0 0
0 0 0 0 0

示例2,题目给出的二维网格 grid:

1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

则有三块岛屿:

1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

二、算法原理 + 代码实现

题目的本质是在二维矩阵中搜索,因此我们可以:

  1. 遍历矩阵,当找到一个未被标记过的岛屿时就更新岛屿的数量并标记,
  2. 然后从这个位置开始向四周深度优先搜索相邻的未被标记过的陆地,直到搜索不到陆地为止。
  3. 当矩阵遍历完毕,返回所记录的岛屿的数量即可

全局变量

为了 dfs 函数递归方便,将矩阵 grid 改成全局变量;mn 记录矩阵的大小;ret 用于记录岛屿的数量。

布尔类型的数组 visit 则用于标记已经发现的岛屿和陆地,防止重复计入;dxdy 方向数组,用于访问指定位置的上下左右四个方向。

java 复制代码
char[][] grid;
int m, n, ret;
boolean[][] visit;
int[] dx = {0, 0, -1, 1};
int[] dy = {-1, 1, 0, 0};

dfs 函数

函数头

dfs 函数的任务是从指定位置出发,访问它的四个方向,因此函数的参数是 rowcol,表示某位置的坐标。

java 复制代码
dfs(int row, int col);

函数体

我们在 dfs 函数体中要做的事情就是:从指定位置(坐标 row, col )出发,逐一访问该位置的上、下、左、右四个方向的位置,看看是否是未记录过的陆地,如果是,就继续递归深搜,否则不进行深搜。

具体就是循环四次然后计算出下一个位置的坐标,判断坐标是否合法,若合法,就进一步判断:

  1. 该坐标在 grid 矩阵中的值是否是 '1' ------ 该位置是陆地
  2. 该坐标的在 visit 中的值是否不等于 "true" ------ 该位置未被标记过

若以上两个条件都满足,就继续递归深搜。

细节问题

回溯

本题不需要回溯操作,我们标记一个岛屿之后不需要将其状态修改回去。

剪枝

由于解法是基于暴搜的,每一个节点都会被遍历到,因此不涉及到剪枝操作。

递归出口

当所有的岛屿都被遍历到并记录之后,就直接退出递归,无需手动设置递归出口。

代码实现

java 复制代码
class Solution {
	char[][] grid;
	int m, n, ret;
	boolean[][] visit;
	int[] dx = {0, 0, -1, 1};
	int[] dy = {-1, 1, 0, 0};

    public int numIslands(char[][] givenGrid) {
        grid = givenGrid; m = grid.length; n = grid[0].length;
        visit = new boolean[m][n];

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1' && !visit[i][j]) {
                    // 找到未被标记过的岛屿,标记该岛屿并更新岛屿数量
                    visit[i][j] = true; ret++;
                    dfs(i, j); // 从该位置开始向四周寻找相邻的陆地
                }
            }
        }

        return ret;
    }

    private void dfs(int row, int col) {
        for (int k = 0; k < 4; k++) {
            int x = row + dx[k], y = col + dy[k];
            if (x >= 0 && x < m && y >= 0 && y < n) {
                if (grid[x][y] == '1' && !visit[x][y]) {
                    // 找到未被标记过的相邻陆地
                    visit[x][y] = true;
                    dfs(x, y);
                }
            }
        }
    }
}

文章到这里就告一段落了,若有错误请尽管指出~

相关推荐
弹简特1 小时前
【Java项目-轻聊】08-用户管理模块-实现获取用户信息+头像上传+显示头像
java·开发语言·springboot
贺国亚1 小时前
Buy领域智能体-Spring-AI全量工程
java·人工智能·spring
不想吃饭e1 小时前
uniapp-图片,视频上传组件封装
java·uni-app·音视频
迷藏4941 小时前
双阶段动态权重匹配系统:高效精准的工业级解决方案
java·junit
开源推荐官2 小时前
2026 三大国产优质开源商城深度测评:VortMall、Tigshop、Jinor 选型全解析
java·开源
We Just Keep growing2 小时前
【MySQL运维篇】——日志、主从复制、分库分表、读写分离
java·运维·数据库·windows·学习·mysql
change_fate2 小时前
ERR_PNPM_WORKSPACE_PKG_NOT_FOUND In ...
java·服务器·前端
好评笔记2 小时前
深度学习面试八股——循环神经网络RNN
人工智能·rnn·深度学习·神经网络·算法·机器学习·aigc
kakawzw2 小时前
微服务组件源码2——Spring Ribbon原理(基于RibbonLoadBalancerClient)
java·微服务·ribbon