Leetcode【DFS BFS】| 200. 岛屿数量(java详细注释版)

这篇博客介绍了LeetCode中‘岛屿数量’问题的解决方案,包括使用DFS和BFS两种方法。文章详细阐述了思路,提出在原网格中搜索并标记已访问节点以避免重复搜索,并分析了两种方法的时间和空间复杂度。
摘要由CSDN通过智能技术生成

Leetcode | 200. 岛屿数量

题目

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
 输入:
 11110
 11010
 11000
 00000
 输出: 1
示例 2:
 输入:
 11000
 11000
 00100
 00011
 输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands

解题

思路

 因为岛屿是连通着的1,很容易想到DFS和BFS,从一个1点出发,可以把它连通着的所有1(连通的邻接点有四个方向:上下左右)搜索出来,这就是一个岛屿。而我们进行几次dfs/bfs搜索就是一共有几个岛屿。详细DFS和BFS的搜索方法介绍见图/树的遍历:深度优先遍历DFS和广度优先遍历BFS详解与java实现
 具体代码怎么设计实现,就有以下几个问题:① 从哪个1出发,怎么选择每个岛屿的第一个1?② 怎么确保下一个搜索选择的1是没有被搜索过的岛屿?
 上述问题的解决方法:本来想着是将二维数组中所有的1用另一种数据结构存储起来,依次遍历作为搜索开始点,搜索过的1就从存储结构里删除;等这次搜索结束后,从存储结构里的下一个1开始下一次搜索。但是实现起来比较麻烦,也需要额外的内存空间。
 另一种更好的解决方法就是在grid数组里原地搜索,不占用额外的内存空间。

  1. 依次遍历整个网格,当遇到1时,就开始dfs/bfs
  2. 然后每次搜索到哪个点就把哪个点的值赋值为0,这样确保了下一次dfs/bfs不会再选择这个点,解决了问题②。
  3. 在遍历整个网格的过程中,进行一个dfs/bfs,岛屿数量res+1, 表示多一个岛屿。

DFS解法

 递归求解

需要注意的是,dfs的递归求解中,遍历到每一个点时,在递归它的邻接点之前,一定要确保它的那个邻接点存在,因为不存在就不用判断/搜索这个点。而这种判断情况很复杂,因为邻接点存在的条件很多样。所以我们写代码时可以采用排除法,反向思考,不判断点是否存在,而是判断点是否不存在,将不存在的情况排除。
具体操作:递归每个点时,不判断每个邻接点是否存在再递归这个邻接点,而是假设都存在先递归邻接点,然后在每次递归的方法里先判断这个点存不存在,将不存在的情况(比如在方格外或不满足条件)列出来,直接返回不用继续递归。

 在该题中,邻接点存在的条件是:

  1. 在该点的水平/竖直方向上的相邻,即上下左右四个点;
  2. 值为1;
  3. 在网格内。

 时间复杂度:O(mn),m和n分别为行数和列数
 空间复杂度:O(mn),因为dfs的深度最坏为整个陆地为mn

class Solution {
   
    public int numIslands(char[][] grid) {
   
        //深度优先搜索 递归
        int res = 0;
        int m = grid.length;//行数
        //特殊情况
        if(grid == null ||m == 0) return 0;
        //因为当rown等于0时,coln根本算不出来,所以要先判断
        int n = grid[0].length; //列数

        for(int i = 0;i < m;i++){
   
            for(int j = 0; j < n; j++){
   
                if(grid[i][j] == '1'){
   
                    res++;
                    //从(i,j)位置开始搜索,将搜索到的1值都标记为0,说明已经访问过&
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值