算法系列-leetcode-200.岛屿数量/419.战舰数量

200. 岛屿数量(中等)

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

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

419. 甲板上的战舰(中等)

给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 board 上放置的 战舰 的数量。

战舰 只能水平或者垂直放置在 board 上。换句话说,战舰只能按 1 x k1 行,k 列)或 k x 1k 行,1 列)的形状建造,其中 k 可以是任意大小。两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。

示例 1:

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

1.深度优先遍历DFS/递归法

这种方法两道题通用。

从一个点出发,若遇到‘1’,即遇到了岛屿,然后向这个‘1’的上下左右的出发,直到遇到‘0’为止,经过的‘1’也变为‘0’,即将岛屿所有节点删除,以免之后重复搜索相同岛屿。

/**
 * @param {character[][]} grid
 * @return {number}
 */
var numIslands = function(grid) {
    let m=grid.length
    let n=grid[0].length
    let res=0
    function turnZoro(i,j){
        if(i>=m||j>=n||i<0||j<0||grid[i][j]=="0") return
        grid[i][j]="0"
        turnZoro(i-1,j)
        turnZoro(i,j-1)
        turnZoro(i+1,j)
        turnZoro(i,j+1)
    }
    for(let i=0;i<m;i++){
        for(let j=0;j<n;j++){
            if(grid[i][j]=="1"){
                turnZoro(i,j)
                res++
            }
        }
    }
    return res
};

2.枚举起点

针对战舰数量问题:你可以实现一次扫描算法,并只使用 O(1) 额外空间,并且不修改 board 的值来解决这个问题吗?

因为题目中给定的两艘战舰之间至少有一个水平或垂直的空位分隔,任意两个战舰之间是不相邻的,因此我们可以通过枚举每个战舰的左上顶点即可统计战舰的个数。除了第一艘,每一个战舰的左、上必定是空位。

即:

满足当前位置所在的值 :board[i][j] = board[i][j]=’X’
满足当前位置的左则为空位,即board[i][j-1] = board[i][j−1]=’.’
满足当前位置的上方为空位,即board[i-1][j] = board[i−1][j]=’.’

/**
 * @param {character[][]} board
 * @return {number}
 */
var countBattleships = function(board) {
    const row = board.length;
    const col = board[0].length;
    let ans = 0;
    for (let i = 0; i < row; ++i) {
        for (let j = 0; j < col; ++j) {
            if (board[i][j] === 'X') {
                if (i > 0 && board[i - 1][j] === 'X') {
                    continue;
                }
                if (j > 0 && board[i][j - 1] === 'X') {
                    continue;
                }
                //
                ans++;
            }
        }
    }
    return ans;
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值