一.数组(18)419. 甲板上的战舰(题目没看懂)

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

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

示例 1:

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

输入:board = [["."]]
输出:0
 

提示:

m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j] 是 '.' 或 'X'
 

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/battleships-in-a-board

官方题解:

方法一:遍历扫描
题目要求找到矩阵中战舰的数量,战舰用’X’ 表示,空位用 ’.’,而矩阵中的战舰的满足以下两个条件:

战舰只能水平或者垂直放置。战舰只能由子矩阵 1×N(1 行,N 列)组成,或者子矩阵N×1(N 行, 1 列)组成,其中 N 可以是任意大小。
两艘战舰之间至少有一个水平或垂直的空位分隔,没有相邻的战舰。
我们遍历矩阵中的每个位置 (i,j)且满足board[i][j]=’X’,并将以 (i,j)(i,j) 为起点的战舰的所有位置均设置为空位,从而我们即可统计出所有可能的战舰。

func countBattleships(board [][]byte) int {
    ans := 0
    m, n := len(board), len(board[0])//m:行,n:列
    for i, row := range board{//i为行号,row为每行这个一维切片
        for j, ch := range row{//j为第i行元素的各个元素的索引,ch为第i行的各个元素
            //相当于遍历数组
            if ch == 'X'{//当前位置存在战舰
                //把当前位置所在的行和列的元素都置为空
                row[j] = '.'//将其置为空
                for k := j + 1; k < n && row[k] == 'X'; k++{//当前行有战舰的地方均置为空
                    row[k] = '.'
                }
                for k := i + 1; k < m && board[k][j] == 'X'; k++{//当前列有战舰的地方均置为空
                    board[k][j] = '.'
                }
                ans++
            }
        }
    }
    return ans
}

方法二:枚举起点
题目进阶要求一次扫描算法,只使用 O(1) 额外空间,并且不修改甲板的值。因为题目中给定的两艘战舰之间至少有一个水平或垂直的空位分隔,任意两个战舰之间是不相邻的,因此我们可以通过枚举每个战舰的左上顶点即可统计战舰的个数。假设矩阵的行数为 row,矩阵的列数 col,矩阵中的位置 (i, j)为战舰的左上顶点,需满足以下条件:

满足当前位置所在的值board[i][j]=’X’;
满足当前位置的左则为空位,即board[i][j−1]=’.’;
满足当前位置的上方为空位,即board[i−1][j]=’.’;
我们统计出所有战舰的左上顶点的个数即为所有战舰的个数。

func countBattleships(board [][]byte) (ans int) {
    for i, row := range board {
        for j, ch := range row {
            if ch == 'X' && !(i > 0 && board[i-1][j] == 'X' || j > 0 && board[i][j-1] == 'X') {
                ans++
            }
        }
    }
    return
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值