力扣 👊 463. 岛屿的周长

512 阅读2分钟

「这是我参与2022首次更文挑战的第 20 天,活动详情查看:2022首次更文挑战

题目链接

463. 岛屿的周长 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

测试用例

示例 1:

image.png

输入:grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
输出:16
解释:它的周长是上面图片中的 16 个黄色的边

条件限制

row == grid.length
col == grid[i].length
1 <= row, col <= 100
grid[i][j]01

题目分析

题目需要我们求湖的周长,但多个单元格相邻的情况下,周长并不会随着单元格的数量线性增长。但是,如果两个相邻的单元格的值存在跳变(即 0->1, 1->0),那么这两个单元格之间的部分就是我们需要求的周长的一部分。

问题就可以简化为,我们从左往右,从上往下遍历二维数组时,判断当前单元格与右侧、下方的坐标值是否跳变。但这种思路,当湖的一部分在数组的四周时,无法通过跳变的方式来判断周长。一个简单的补救措施,就是为这个二维数组包裹一层 0

代码实现

var islandPerimeter = function(grid) {
    // 左右补 0
    grid.forEach(arr => {
        arr.push(0);
        arr.unshift(0);
    })
    let m = grid.length + 2,
        n = grid[0].length;
    // 上下补 0
    let arr = new Array(m).fill(0);
    grid.push(arr);
    grid.unshift(arr);
    let count = 0;
    // 横向遍历,纵向遍历,记录跳变
    for (let i = 0; i < m - 1; i++) {
        for (let j = 0; j < n - 1; j++) {
            if (grid[i][j] ^ grid[i + 1][j] == 1) count++;
            if (grid[i][j] ^ grid[i ][j+ 1] == 1) count++;
        }
    }
    return count;
};

image.png

解法2

同样是依据跳变的思路来计算周长,但是不为数组补一圈 0,直接硬算。

并且,当坐标值为 1 且压在边界上时,判断累加最外边的周长

var islandPerimeter = function(grid) {
    let count = 0;
    let m = grid.length,
        n = grid[0].length;
    // 横向遍历,纵向遍历,记录跳变
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (i < m - 1 && grid[i][j] ^ grid[i + 1][j] == 1) count++;
            if (j < n - 1 && grid[i][j] ^ grid[i][j + 1] == 1) count++;
            if (grid[i][j] == 1) {
                if (i == 0) count++;
                if (i == m - 1) count++;
                if (j == 0) count++;
                if (j == n - 1) count++;
            }
        }
    }
    return count;
}; 

image.png