代码随想录算法训练营第五十一天|99.岛屿数量 深搜 、99.岛屿数量 广搜、岛屿的最大面积

#99. 岛屿数量

深度优先搜索:

每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

本题思路:用遇到一个没有遍历过的节点陆地,计数器就加一,然后把该节点陆地所能遍历到的陆地都标记上。在遇到标记过的陆地节点和海洋节点的时候直接跳过。 这样计数器就是最终岛屿的数量。

def dfs(grid, visited, x, y):
    if visited[x][y] or grid[x][y] == 0:
        return  # 终止条件:访问过的节点 或者 遇到海水
    visited[x][y] = True  # 标记访问过
    directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]  # 四个方向(上右下左的顺序)
    for dx, dy in directions:
        nextx = x + dx
        nexty = y + dy
        if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):  # 检查是否越界
            dfs(grid, visited, nextx, nexty)

def main():
    n, m = map(int, input().split())
    grid = [list(map(int, input().split())) for _ in range(n)]
    visited = [[False] * m for _ in range(n)]

    result = 0
    for i in range(n):
        for j in range(m):
            if not visited[i][j] and grid[i][j] == 1:
                result += 1  # 遇到没访问过的陆地,+1
                dfs(grid, visited, i, j)  # 将与其链接的陆地都标记上 True

    print(result)

if __name__ == "__main__":
    main()

广度优先搜索:

from collections import deque

def bfs(grid, visited, x, y):
    # 使用deque实现队列
    queue = deque([(x, y)])
    visited[x][y] = True  # 加入队列后立即标记为已访问
    directions = [[0,1],[1,0],[0,-1],[-1,0]]
    while queue:
        curx, cury = queue.popleft()  # 从队列中取出当前位置
        for dx, dy in directions:  # 遍历四个方向
            nextx, nexty = curx + dx, cury + dy
            # 检查新位置是否在网格内
            if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):
                # 如果新位置未被访问且是陆地,则加入队列并标记为已访问
                if not visited[nextx][nexty] and grid[nextx][nexty] == 1:
                    queue.append((nextx, nexty))
                    visited[nextx][nexty] = True

def main():
    n, m = map(int, input().split())
    # 使用列表推导式初始化网格和访问记录
    grid = [list(map(int, input().split())) for _ in range(n)]
    visited = [[False] * m for _ in range(n)]

    result = 0
    # 遍历网格,找到未访问的陆地,计算陆地区域数量
    for i in range(n):
        for j in range(m):
            if not visited[i][j] and grid[i][j] == 1:
                result += 1
                bfs(grid, visited, i, j)

    print(result)

if __name__ == "__main__":
    main()

100. 岛屿的最大面积

DFS写法:

dfs只处理下一个节点,即在主函数遇到岛屿就计数为1,dfs处理接下来的相邻陆地

def dfs(grid, visited, x, y):
    # 定义四个方向
    directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
    if visited[x][y] or grid[x][y] == 0:  # 终止条件:访问过的节点 或者 遇到海水
        return
    visited[x][y] = True  # 标记访问过
    global count  # 使用全局变量count,因为需要在dfs调用之间共享状态
    count += 1
    for dx, dy in directions:
        nextx = x + dx
        nexty = y + dy
        # 检查新坐标是否越界
        if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):
            dfs(grid, visited, nextx, nexty)  # 递归调用dfs

def find_max_island_area(grid):
    # 获取网格的行数和列数
    n = len(grid)
    m = len(grid[0])
    # 初始化访问记录矩阵
    visited = [[False] * m for _ in range(n)]
    # 初始化结果变量
    result = 0

    for i in range(n):  # 遍历网格
        for j in range(m):
            if not visited[i][j] and grid[i][j] == 1:  # 如果是未访问的陆地
                count = 0  # 重置计数器
                dfs(grid, visited, i, j)  # 执行深度优先搜索
                result = max(result, count)  # 更新最大陆地区域大小

    return result

BFS写法:

from collections import deque

class Solution:
    def maxAreaOfIsland(self, grid):
        # 定义四个方向
        self.dir = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        # 初始化结果变量
        result = 0

        # 遍历网格,寻找未访问的陆地
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    # 使用bfs算法计算陆地区域大小
                    area = self.bfs(grid, i, j)
                    result = max(result, area)

        return result

    def bfs(self, grid, x, y):
        # 检查坐标是否越界
        if x < 0 or x >= len(grid) or y < 0 or y >= len(grid[0]):
            return 0

        # 访问记录集合
        visited = [[False] * len(grid[0]) for _ in range(len(grid))]
        # 初始化队列
        queue = deque([(x, y)])
        # 初始化陆地区域计数
        count = 1

        while queue:
            # 从队列中取出当前坐标
            xx, yy = queue.popleft()
            # 标记当前坐标为已访问
            visited[xx][yy] = True

            # 遍历四个方向
            for dx, dy in self.dir:
                nextx, nexty = xx + dx, yy + dy
                
                # 如果新坐标在网格内且未被访问过且是陆地
                if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]) and not visited[nextx][nexty] and grid[nextx][nexty] == 1:
                    # 将新坐标加入队列
                    queue.append((nextx, nexty))
                    # 标记新坐标为已访问
                    visited[nextx][nexty] = True
                    # 更新陆地区域计数
                    count += 1

        return count

# 示例使用
# 假设有一个网格
grid = [
    [1, 1, 0, 0, 0],
    [1, 1, 0, 0, 0],
    [0, 0, 0, 1, 1],
    [0, 0, 0, 1, 1]
]
# 创建Solution实例并调用maxAreaOfIsland方法
solution = Solution()
print(solution.maxAreaOfIsland(grid))

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值