Copilot Chatbot SWE · Internal Phone Screen Coding

Microsoft 岛屿题:增加一块陆地后的最大岛面积

给已有岛屿标号与面积,再枚举每个水格,合并最多四个不同相邻岛,避免同一岛重复计数。

题目重点:给已有岛屿标号与面积,再枚举每个水格,合并最多四个不同相邻岛,避免同一岛重复计数。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • grid 为矩形 0/1 网格,1 是陆地,按上下左右四邻接。
  • 最多把一格 0 改为 1;全陆地时无需改动并返回整片面积。若必须恰好翻一格,全陆地的输入应另定义无解。
  • 返回最大连通岛屿的格子数,不返回翻转位置;空网格训练版返回 0。

解题路线

  1. 第一遍只访问原有陆地:对每个未标记的 1 用 DFS/BFS 赋唯一 componentId,记录 area[id]。每格恰好入栈一次。
  2. 第二遍枚举每个 0:收集四邻陆地的不同 id,候选面积为 1+这些 id 的面积之和。对同一岛出现的两条边只能加一次。
  3. 答案取原有最大面积和所有候选的最大值;原有最大值处理全陆地,也覆盖‘最多翻一格’语义。正确性来自任何一次翻转只可能连接与该水格四邻的旧岛,其余岛保持不变。
  4. 若要求一串动态 add 操作后持续返回最大面积,则应改用并查集增量维护;本题是一格一次性选择,组件标号更直接。

手动走一遍

[[1,0,1],[1,0,1]] 两列原岛面积分别 2、2。翻中间任一水格时连接两个不同 id,得到 1+2+2=5;若中间水格的上下左右有两格属于同一岛,id 集合保证面积只加一次。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

"""Largest 4-neighbor island area after changing at most one zero to one."""


def largest_island_after_one_addition(grid: list[list[int]]) -> int:
    if not grid:
        return 0
    rows, cols = len(grid), len(grid[0])
    if any(len(row) != cols or any(value not in (0, 1) for value in row) for row in grid):
        raise ValueError("rectangular binary grid required")
    if cols == 0:
        return 0

    island_id = [[0] * cols for _ in range(rows)]
    area = {0: 0}
    next_id = 1
    for start_r in range(rows):
        for start_c in range(cols):
            if grid[start_r][start_c] == 0 or island_id[start_r][start_c] != 0:
                continue
            island_id[start_r][start_c] = next_id
            stack = [(start_r, start_c)]
            size = 0
            while stack:
                r, c = stack.pop()
                size += 1
                for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1 and island_id[nr][nc] == 0:
                        island_id[nr][nc] = next_id
                        stack.append((nr, nc))
            area[next_id] = size
            next_id += 1

    best = max(area.values())
    for r in range(rows):
        for c in range(cols):
            if grid[r][c] != 0:
                continue
            neighbors = set()
            for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
                nr, nc = r + dr, c + dc
                if 0 <= nr < rows and 0 <= nc < cols:
                    neighbors.add(island_id[nr][nc])
            best = max(best, 1 + sum(area[component] for component in neighbors))
    return best

复杂度

R×C 网格:两遍各 O(RC) 时间;标号矩阵、DFS 栈与面积表合计 O(RC) 空间。每个水格最多查看四邻,常数级去重。

易错点与追问

容易失分的边界

  • 每尝试一个水格就全图重算,退化 O((RC)²)。
  • 同一旧岛从两个方向邻接时累加两次面积。
  • 对原输入就地翻转而未还原,后续候选受污染。
  • 把对角线也算邻接却没写明。
  • 全陆地返回 0 而不是当前面积。

继续深挖

  • 若最多可翻两格,为什么简单取两个单格收益之和不正确?
  • 若动态逐个加陆地并每步报告岛屿数及最大面积,怎样用并查集?
  • 返回最优翻转坐标时并列如何定义?
✓已复制微信号!