Leetcode 200、419、695小岛问题(动态规划)

373 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

力扣中第200、419、695题,题型相似。基本都是利用动态规划进行解题,其中,这一题型的解题方式称为“沉没”方式,下面会详细介绍:

下面先看一下这三道题的题目有何相似之处

image.png

输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1

1655706727244.jpg

输入: board = [        ["X",".",".","X"],
        [".",".",".","X"],
        [".",".",".","X"]
     ]
输出: 2

image.png

输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],
              [0,0,0,0,0,0,0,1,1,1,0,0,0],
              [0,1,1,0,1,0,0,0,0,0,0,0,0],
              [0,1,0,0,1,1,0,0,1,0,1,0,0],
              [0,1,0,0,1,1,0,0,1,1,1,0,0],
              [0,0,0,0,0,0,0,0,0,0,1,0,0],
              [0,0,0,0,0,0,0,1,1,1,0,0,0],
              [0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 

利用下图对以上三道题的异同进行分析

image.png

题目分析:

第一道题(Leetcode200)与第二道题(Leetcode419)虽然表述不同,但是所求的结果是一样的。只要将“战舰(X)”想象成为“小岛(1)”,将“空位(.)”想象成“水(0)”,那么他们就是一道题。无非是求上面的二维数组中有多少个带颜色的大区域。第三道题(Leetcode695),则只是对上面两道题有一个小小的改动,这个改动就是要求出这些带颜色的区域中最大区域所含有元素1的数量。

解题及思路:

思路:

以第一题(Leetcode200)为例 大体执行的思路就是我们需要循环二维数组,当遇到1时将其变为0,这里称之为“沉没”。并且以当前数字为中心向四周扩散,遇到1则将其“沉没”为0,直到没有1无法扩散,这时则记录为1个小岛。这时循环还在继续,遇到1同样将其“沉没”为0并向四周扩散进行“沉没”操作,因为上一次的“沉没”将1都变为了0,所以不会重复计算不相邻的1的个数,这时记录为2个小岛。第二题(Leetcode419)只是情景以及记号变化,其余都一样。

题解:

1、首先定义count作为返回的小岛数量;

2、定义dfs(深度搜索)函数,函数接收两个参数,“小岛”的横纵坐标,使用该函数用来“沉没”小岛。函数中首先处理边界条件,当数字越界或者是水(0)时则直接return返回。 执行完上述,则直接将坐标所在位置沉没为0。随后将调用自身函数四次,分别向四周扩散;

3、遍历该二维数组,遇到1时,将小岛数量加1,随后调用dfs函数,将二维数组坐标传入;

4、最后,返回count就是岛屿的数量;

代码

/**
 * @param {character[][]} grid
 * @return {number}
 */
var numIslands = function(grid) {
    let count = 0;
     function dfs(row,col) {
        if(row < 0 || row >= grid.length || col < 0 || col >= grid[0].length || grid[row][col] ==="0" ) { // 防止越界
            return;
        }
        grid[row][col] = "0";
        // 运用递归向四周扩散
        dfs(row-1, col);
        dfs(row+1, col);
        dfs(row, col-1);
        dfs(row, col+1);
    }
    for(let row = 0; row < grid.length; row++) {
        for(let col = 0; col < grid[0].length; col++) {
            if (grid[row][col] === "1") {
                count++;
                dfs(row,col);
            }
        }
    }
    return count;
};

岛屿最大面积

只需要针对上题做些许改动。

定义返回的最大面积result

  • def函数中 1、 越界时返回 return 0

2、需要在def函数中记录被沉没掉的1的数量,并返回;

  • 二维数组循环中

1、 找到岛屿沉没面积最大数量并赋值给result

最后返回result

代码

/**
 * @param {number[][]} grid
 * @return {number}
 */
var maxAreaOfIsland = function(grid) {
    let result = 0;
    for(let row = 0; row < grid.length; row++) {
        for(let col = 0; col < grid[0].length; col++) {
            if (grid[row][col] === 1) {
                const count = def(row, col);
                result = Math.max(result, count); // 找到岛屿沉没面积最大数量
            }
        }
    }

    function def(row, col) {
        if (row < 0 || row > grid.length - 1 || col < 0 || col > grid[0].length -1 || grid[row][col] === 0) {
            return 0;
        }
        grid[row][col] = 0;
        // 记录被沉没掉的1的数量
        let count = 1;
        count += def(row - 1, col);
        count += def(row + 1, col);
        count += def(row, col - 1);
        count += def(row, col + 1);
        return count;
    }

    return result;
};

这道题二维数组中是数字,上一道题是字符串,需要注意哦~

最近好懒哦~ 活动也不想参加 丧丧的~🥱