题目描述

✅ 463. 岛屿的周长

image-20260928235747968

image-20260928235747969

题意分析

网格中的陆地通过上下左右相连,组成唯一一个没有湖泊的岛屿。每个格子的边长为 1,要求陆地与水域相接的边长总和;网格外也视为水域,所以贴着网格边界的陆地边同样计入周长。

解法:统计陆地和相邻边

核心思路

[!blue]

先把每个陆地格当成独立的小岛,各贡献四条边。这样,陆地与水域相接的边恰好计入一次,而两个陆地格之间的共享边会从两侧各计入一次。共享边不属于周长,必须把这两份都扣掉。因此答案就是陆地格数乘 4,再减去共享边数乘 2。

为了让每条共享边只扣一次,每个陆地格只检查上方和左方:竖直相邻的一对由下面的格子处理,水平相邻的一对由右边的格子处理。所有共享边都会被覆盖,也不会重复扣除;水域和网格外侧没有相邻陆地,无需扣减,便自然留下了周长。

整个过程只读取网格并累加结果,不需要搜索岛屿、修改陆地标记或维护访问数组。

解题步骤

  • 遍历全部行和列,跳过水格。
  • 陆地先加四。
  • 上方是陆地减二,左方是陆地也减二。
  • 全部格子处理完成后,返回累计周长。

代码实现

class Solution {
    public int islandPerimeter(int[][] grid) {
        int perimeter = 0;

        for (int row = 0; row < grid.length; row++) {
            for (int col = 0; col < grid[0].length; col++) {
                if (grid[row][col] == 0) {
                    continue;
                }

                perimeter += 4;

                // 共享边此前计了两份,只检查上和左避免重复扣除
                if (row > 0 && grid[row - 1][col] == 1) {
                    perimeter -= 2;
                }

                if (col > 0 && grid[row][col - 1] == 1) {
                    perimeter -= 2;
                }
            }
        }

        return perimeter;
    }
}
func islandPerimeter(grid [][]int) int {
    perimeter := 0
    for row := 0; row < len(grid); row++ {
        for col := 0; col < len(grid[0]); col++ {
            if grid[row][col] == 0 {
                continue
            }
            perimeter += 4
            // 共享边此前计了两份,只检查上和左避免重复扣除
            if row > 0 && grid[row-1][col] == 1 {
                perimeter -= 2
            }
            if col > 0 && grid[row][col-1] == 1 {
                perimeter -= 2
            }
        }
    }
    return perimeter
}

复杂度分析

  • 时间复杂度:$O(mn)$,其中 $m$、$n$ 分别为行数和列数,每个格子只做常数次判断。
  • 空间复杂度:$O(1)$,只保存累计值与下标。

关键点总结

[!green]

  • 共享边按两份扣除。
  • 只选每个维度的一个方向统计相邻对。
  • 第一行没有上方格子,第一列没有左方格子;先检查下标边界,外侧的边就会正常保留。

易错点总结

[!yellow]

  • 四方向都减二,会把共享边重复扣除。
  • 只减一,会留下本应删除的另一份共享边。
  • 列循环误用行数,会漏扫或越界;题目保证网格为非空矩形,列数应取 grid[0] 的长度。
  • 对角线接触不构成共享边,不能扣减周长。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2025/32824972
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!