LeetCode 463. 岛屿的周长

463. 岛屿的周长

题目描述

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

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

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

LeetCode 463. 岛屿的周长_第1张图片

解题思路

思路一:DFS(深度优先搜索)

岛屿的周长就是岛屿方格和非岛屿方格相邻的边的数量。注意,这里的非岛屿方格,既包括水域方格,也包括网格的边界。
对应到 DFS 遍历中,就是:每当在 DFS 遍历中,从一个岛屿方格走向一个非岛屿方格,就将周长加 1。
实现代码如下:

/**
 * @param {number[][]} grid
 * @return {number}
 */
var islandPerimeter = function(grid) {
    let res = 0, rowLen = grid.length, colLen = grid[0].length;

    const dfs = function (row, col) {
        // 从一个岛屿方格走向网格边界、水域方格,周长加 1
        if (row < 0 || row >= rowLen || col < 0 || col >= colLen || grid[row][col] == 0) {
            return 1;
        }
        // 已遍历过(值为2)的岛屿在这里会直接返回,不会重复遍历
        if (grid[row][col] != 1) {
            return 0;
        }
        grid[row][col] = 2; // 标记为已遍历的
        return dfs(row, col - 1) + dfs(row - 1, col) +  dfs(row + 1, col) +  dfs(row, col + 1);
    }

    for (let row = 0; row < rowLen; row++) {
        for (let col = 0; col < colLen; col++) {
            if (grid[row][col] == 1) { 
                res += dfs(row, col);
            }
        }
    } 
    return res;
};
  • 时间复杂度:O(nm),其中 n 为网格的高度,m 为网格的宽度。每个格子至多会被遍历一次,因此总时间复杂度为 O(nm)。

  • 空间复杂度:O(nm)。深度优先搜索复杂度取决于递归的栈空间,而栈空间最坏情况下会达到 O(nm)。

思路二: 普通遍历

遍历整个数组,碰到0或者边界计数

/**
 * @param {number[][]} grid
 * @return {number}
 */
var islandPerimeter = function(grid) {
    let count = 0, rowLen = grid.length, colLen = grid[0].length;
    for (let row = 0; row < rowLen; row++) {
        for (let col = 0; col < colLen; col++) {
            if (grid[row][col] == 1) {   
                if (row == 0 || grid[row - 1][col] == 0) count++;
                if (row == rowLen - 1 || grid[row + 1][col] == 0)  count++;
                if (col == 0 || grid[row][col - 1] == 0)  count++;
                if (col == colLen - 1 || grid[row][col + 1] == 0)  count++;
            }
        }
    } 
    return count;
};

还有以下方法是参考https://leetcode.cn/problems/island-perimeter/solution/shou-hua-tu-jie-463-dao-yu-de-zhou-chang-by-xiao_b/

思路如下:
一块土地 4 个周长,但岛上的土地存在接壤,每一块接壤,会减掉 2 个边长。

所以,总周长 = 4 * 土地个数 - 2 * 接壤边的条数。

遍历矩阵,遍历到土地,就 land++,如果它的右/下边也是土地,则 border++,遍历结束后代入公式

实现代码如下:

/**
 * @param {number[][]} grid
 * @return {number}
 */
var islandPerimeter = function(grid) {
    let land = 0, // 岛屿格子数量
        edge = 0, // 岛屿格子之间的相邻边
        rowLen = grid.length, colLen = grid[0].length;
    for (let row = 0; row < rowLen; row++) {
        for (let col = 0; col < colLen; col++) {
            if (grid[row][col] == 1) { 
                land++;
                // 判断右边是不是 陆地格子
                if (row < rowLen - 1 && grid[row + 1][col] == 1) {
                    edge++;
                }
                // 判断下面是不是 陆地格子
                if (col < colLen - 1 && grid[row][col + 1] == 1) {
                    edge++;
                } 
            }
        }
    } 
    return 4 * land - 2 * edge;
};

参考资料

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

你可能感兴趣的:(LeetCode,leetcode,深度优先,算法)