代码随想录算法训练营第五十二天|KM101.孤岛的总面积|KM102.沉没孤岛|KM103.水流问题|KM104.建造最大岛屿

101. 孤岛的总面积

python 复制代码
direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
result = 0

def dfs(grid, y, x):
    grid[y][x] = 0
    global result
    result += 1

    for i, j in direction:
        next_x = x + j
        next_y = y + i
        if (next_x < 0 or next_y < 0 or
                next_x >= len(grid[0]) or next_y >= len(grid)
        ):
            continue
        if grid[next_y][next_x] == 1 and not visited[next_y][next_x]:
            visited[next_y][next_x] = True
            dfs(grid, next_y, next_x)

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

for i in range(n):
    grid.append(list(map(int, input().split())))

# 处理边界
for j in range(m):
    # 上边界
    if grid[0][j] == 1 and not visited[0][j]:
        visited[0][j] = True
        dfs(grid, 0, j)
    # 下边界
    if grid[n - 1][j] == 1 and not visited[n - 1][j]:
        visited[n - 1][j] = True
        dfs(grid, n - 1, j)

for i in range(n):
    # 左边界
    if grid[i][0] == 1 and not visited[i][0]:
        visited[i][0] = True
        dfs(grid, i, 0)
    # 右边界
    if grid[i][m - 1] == 1 and not visited[i][m - 1]:
        visited[i][m - 1] = True
        dfs(grid, i, m - 1)

# 计算孤岛总面积
result = 0  # 初始化

for i in range(n):
    for j in range(m):
        if grid[i][j] == 1 and not visited[i][j]:
            visited[i][j] = True
            dfs(grid, i, j)

# 输出孤岛的总面积
print(result)

102. 沉没孤岛

思路:

从地图周边出发,将周边空格相邻的陆地都做上标记,然后在遍历一遍地图,遇到 陆地 且没做过标记的,那么都是地图中间的 陆地 ,全部改成水域就行。

**方法:**直接改陆地为其他特殊值作为标记的方式进行;

步骤一:深搜或者广搜将地图周边的 1 (陆地)全部改成 2 (特殊标记)

步骤二:将水域中间 1 (陆地)全部改成 水域(0)

步骤三:将之前标记的 2 改为 1 (陆地)

python 复制代码
def dfs(grid, x, y):
    grid[x][y] = 2
    directions = [[-1, 0], [0, -1], [1, 0], [0, 1]]
    for dx, dy in directions:
        next_x, next_y = x + dx, y + dy
        # 超过边界
        if next_x < 0 or next_x >= len(grid) or next_y < 0 or next_y >= len(grid[0]):
            continue
        if grid[next_x][next_y] == 0 or grid[next_x][next_y] == 2:
            continue
        dfs(grid, next_x, next_y)

def main():
    n, m = map(int, input().split())
    grid = [[False] * m for _ in range(n)]
    # 步骤一
    # 从左侧边,和右侧边,向中间遍历
    for i in range(n):
        if grid[i][0] == 1:
            dfs(grid, i, 0)
        if grid[i][m-1] == 1:
            dfs(grid, i, m-1)
    # 从上边和下边,向中间遍历
    for j in range(m):
        if grid[0][j] == 1:
            dfs(grid, 0, j)
        if grid[n-1][j] == 1:
            dfs(grid, n-1, j)
    # 步骤二、步骤三
    for i in range(n):
        for j in range(m):
            if grid[i][j] == 1:
                grid[i][j] = 0
            if grid[i][j] == 2:
                grid[i][j] == 1
    # 打印结果
    for row in grid:
        print(' '.join(map(str, row)))

if __name__ == '__main__':
    main()

103. 水流问题

**想法:**遍历每个点,然后看这个点能不能同时到达第一组边界和第二组边界

**优化方法:**没想到,也有待理解,只按照题解敲了代码

python 复制代码
first = set()
second = set()
directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]


def dfs(i, j, graph, visited, side):
    if visited[i][j]:
        return

    visited[i][j] = True
    side.add((i, j))

    for x, y in directions:
        new_x = i + x
        new_y = j + y
        if (
                0 <= new_x < len(graph)
                and 0 <= new_y < len(graph[0])
                and int(graph[new_x][new_y]) >= int(graph[i][j])
        ):
            dfs(new_x, new_y, graph, visited, side)


def main():
    global first
    global second

    N, M = map(int, input().strip().split())
    graph = []
    for _ in range(N):
        row = input().strip().split()
        graph.append(row)

    # 是否可到达第一边界
    visited = [[False] * M for _ in range(N)]
    for i in range(M):
        dfs(0, i, graph, visited, first)
    for i in range(N):
        dfs(i, 0, graph, visited, first)

    # 是否可到达第二边界
    visited = [[False] * M for _ in range(N)]
    for i in range(M):
        dfs(N - 1, i, graph, visited, second)
    for i in range(N):
        dfs(i, M - 1, graph, visited, second)

    # 可到达第一边界和第二边界
    res = first & second

    for x, y in res:
        print(f"{x} {y}")


if __name__ == "__main__":
    main()

104. 建造最大岛屿

要求:最多可以将矩阵中的一格水变为一块陆地;

思路:遍历地图尝试 将每一个 0 改成1,然后去搜索地图中的最大的岛屿面积;

优化思路:用一次深搜把每个岛屿的面积记录下来就好;

第一步:一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map记录,key为岛屿编号,value为岛屿面积

第二步:再遍历地图,遍历0的方格(因为要将0变成1),并统计该1(由0变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

本题没有理解,暂时放一放;

python 复制代码
from typing import List
from collections import defaultdict

class Solution:
    def __init__(self):
        self.direction = [(1,0),(-1,0),(0,1),(0,-1)]
        self.res = 0
        self.count = 0
        self.idx = 1
        self.count_area = defaultdict(int)

    def max_area_island(self, grid: List[List[int]]) -> int:
        if not grid or len(grid) == 0 or len(grid[0]) == 0:
            return 0

        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    self.count = 0
                    self.idx += 1
                    self.dfs(grid,i,j)
        # print(grid)
        self.check_area(grid)
        # print(self.count_area)
        
        if self.check_largest_connect_island(grid=grid):
            return self.res + 1
        return max(self.count_area.values())
    
    def dfs(self,grid,row,col):
        grid[row][col] = self.idx
        self.count += 1
        for dr,dc in self.direction:
            _row = dr + row 
            _col = dc + col 
            if 0<=_row<len(grid) and 0<=_col<len(grid[0]) and grid[_row][_col] == 1:
                self.dfs(grid,_row,_col)
        return

    def check_area(self,grid):
        m, n = len(grid), len(grid[0])
        for row in range(m):
            for col in range(n):
                  self.count_area[grid[row][col]] = self.count_area.get(grid[row][col],0) + 1
        return

    def check_largest_connect_island(self,grid):
        m, n = len(grid), len(grid[0])
        has_connect = False
        for row in range(m):
            for col in range(n):
                if grid[row][col] == 0:
                    has_connect = True
                    area = 0
                    visited = set()
                    for dr, dc in self.direction:
                        _row = row + dr 
                        _col = col + dc
                        if 0<=_row<len(grid) and 0<=_col<len(grid[0]) and grid[_row][_col] != 0 and grid[_row][_col] not in visited:
                            visited.add(grid[_row][_col])
                            area += self.count_area[grid[_row][_col]]
                            self.res = max(self.res, area)
                            
        return has_connect




def main():
    m, n = map(int, input().split())
    grid = []

    for i in range(m):
        grid.append(list(map(int,input().split())))

    
    sol = Solution()
    print(sol.max_area_island(grid))

if __name__ == '__main__':
    main()
相关推荐
CoovallyAIHub3 分钟前
无人机方案如何让桥梁监测更安全、更智能?融合RTK与超高分辨率成像,优于毫米精度
深度学习·算法·计算机视觉
lingran__6 分钟前
C语言制作扫雷游戏(拓展版赋源码)
c语言·算法·游戏
self_myth9 分钟前
【考研/面试必备】操作系统核心原理与IPO机制深度解析
大数据·算法
Calihen的学习日志26 分钟前
【Pandas】3.1-数据预处理:列的基本操作
python·pandas
打螺丝否28 分钟前
稠密矩阵和稀疏矩阵的对比
python·机器学习·矩阵
这里有鱼汤29 分钟前
你以为 FastAPI 足够强?其实 Litestar 能让你的项目更轻量高效
后端·python
Greedy Alg30 分钟前
LeetCode 240. 搜索二维矩阵 II
算法·leetcode·职场和发展
墨染点香35 分钟前
LeetCode 刷题【68. 文本左右对齐】
算法·leetcode·职场和发展
GalaxyPokemon37 分钟前
LeetCode - 202. 快乐数
算法·leetcode·职场和发展
吃着火锅x唱着歌39 分钟前
LeetCode 522.最长特殊序列2
算法·leetcode·职场和发展