📜  在给定矩阵中找到封闭岛的数量(1)

📅  最后修改于: 2023-12-03 14:51:32.924000             🧑  作者: Mango

在给定矩阵中找到封闭岛的数量

在给定矩阵中,封闭岛是由陆地包围并包含在内的岛屿。也就是说,岛屿的四周必须被海洋或者矩阵的边界包围,岛屿内部不能有海洋。现在我们要写一个程序来计算给定矩阵中封闭岛的数量。

方法

我们可以使用深度优先搜索(DFS)来求解。具体思路如下:

  1. 对每个格子进行遍历,如果发现一个陆地,则以此陆地为起点进行深度优先搜索;
  2. 深度优先搜索的过程中,我们遇到了越界的情况,或者遇到了海洋格子,说明此次搜索到了边界,该岛屿不是封闭岛;
  3. 如果我们搜索完所有的格子,发现该岛屿内的所有陆地都被陆地或边界包围,则该岛屿为封闭岛。

实现代码如下:

def closed_island(grid: List[List[int]]) -> int:
    if not grid or not grid[0]:
        return 0
    
    def dfs(i: int, j: int) -> bool:
        if i < 0 or i >= m or j < 0 or j >= n:
            return False
        if grid[i][j] == 1:
            return True
        if grid[i][j] == -1:
            return False
        
        grid[i][j] = -1
        
        is_closed = all([dfs(i-1, j), dfs(i+1, j), dfs(i, j-1), dfs(i, j+1)])
        
        grid[i][j] = 0
        
        return is_closed
    
    m, n = len(grid), len(grid[0])
    
    count = 0
    
    for i in range(m):
        for j in range(n):
            if grid[i][j] == 0:
                if dfs(i, j):
                    count += 1
                    
    return count
解释

上述代码中,我们定义了一个内部函数dfs,用于进行深度优先搜索。具体实现如下:

  • 如果当前坐标(i, j)越界,返回False;
  • 如果当前坐标(i, j)为陆地,返回True;
  • 如果当前坐标(i, j)为海洋,返回False;
  • 如果当前坐标(i, j)已经被标记为已访问(即-1),返回False;
  • 标记当前坐标为已访问,即-1;
  • 尝试所有四个方向进行深度优先搜索;
  • 取四个方向搜索的结果的与(and)操作,如果全部为True,则说明该岛屿为封闭岛,返回True,否则返回False;
  • 回溯,将当前坐标的状态恢复为0。

在for循环中,我们对每个格子进行遍历。如果发现该格子为陆地,并且搜索结果为True,说明该岛屿为封闭岛,计数器加1。

最后,返回计数器的值即可。

复杂度分析

该算法的时间复杂度为$O(mn)$,其中m和n分别为矩阵的行数和列数。具体分析如下:

  • 对于每个格子,我们至多遍历一次,所以总时间复杂度为$O(mn)$;
  • 深度优先搜索的递归栈的深度最大为$\min(m, n)$,所以空间复杂度为$O(\min(m, n))$。

总结来说,该算法的时间复杂度略高于线性,空间复杂度较低,可以满足大部分场景的需求。