持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情.
LeetCode 419.甲板上的战舰
题目描述
给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 board 上放置的 战舰 的数量。
战舰 只能水平或者垂直放置在 board 上。换句话说,战舰只能按 1 x k(1 行,k 列)或 k x 1(k 行,1 列)的形状建造,其中 k 可以是任意大小。两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。
进阶:你可以实现一次扫描算法,并只使用 O(1) 额外空间,并且不修改 board 的值来解决这个问题吗?
解题思路
思路一:DFS(深度优先搜索)
先不考虑空间复杂度, 那么这道题跟LeetCode 200. 岛屿数量 - 掘金 (juejin.cn)解法一样,实现代码如下:
/**
* @param {character[][]} board
* @return {number}
*/
var countBattleships = function(board) {
let count = 0, rowLen = board.length, colLen = board[0].length;
const dfs = function (row, col) {
if (row < 0 || row >= rowLen || col < 0 || col >= colLen || board[row][col] === '.') {
return;
}
board[row][col] = '.'; // 沉没
dfs(row - 1, col);
dfs(row + 1, col);
dfs(row, col + 1);
dfs(row, col - 1);
}
for (let row = 0; row < rowLen; row++) {
for (let col = 0; col < colLen; col++) {
if (board[row][col] === 'X') {
count++;
dfs(row, col);
}
}
}
return count;
};
但如何只使用 O(1) 额外空间,并且不修改 board 的值来解决这个问题呢?
思路二:枚举起点
根据题意, 我们已知两艘战舰不会相邻,且战舰只能是1xk或者kx1的形式;所以,我们搜索的时候其实不用搜索四个方向,只需要查找每个战舰的左上顶点即可统计战舰的个数。及满足以下条件即可:
- 满足当前位置所在的值 board[row][col] === 'X';
- 满足当前位置的左则为空位,即 board[row][col−1] === '.';
- 满足当前位置的上方为空位,即 board[row−1][col] === '.';
实现代码如下:
/**
* @param {character[][]} board
* @return {number}
*/
var countBattleships = function(board) {
let count = 0, rowLen = board.length, colLen = board[0].length;
for (let row = 0; row < rowLen; row++) {
for (let col = 0; col < colLen; col++) {
if (board[row][col] === 'X') {
if (row > 0 && board[row - 1][col] === 'X') {
continue;
}
if (col > 0 && board[row][col - 1] === 'X') {
continue;
}
count++;
}
}
}
return count;
};
-
时间复杂度:O(m×n),其中 m 是矩阵的行数,n 是矩阵的列数,我们只需要遍历一遍矩阵中每个位置即可。
-
空间复杂度: O(1)