419. 棋盘上的战舰
1. 题目简介
难度:中等,原题链接:419. 棋盘上的战舰。
给你一个大小为 m x n 的矩阵 board ,表示甲板,其中,每个单元格用
'X'表示战舰占据的一格,用'.'表示空位 ,返回在甲板 board 上放置的战舰数量。战舰 只能水平或者垂直放置在 board 上。换句话说,战舰只能按 1 x k(1 行,k 列)或 k x 1(k 行,1 列)的形状建造,其中 k 可以是任意大小。两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。
2. 问题分析
每艘战舰只统计一个格子,就能避免重复计数。题目保证战舰是一条水平或竖直的直线,而且不同战舰不会水平或竖直相邻,因此可以只统计每艘战舰最左端或最上端的格子。
按从上到下、每行从左到右的顺序扫描。对于值为 X 的格子 (i, j):
- 上方也是
X,说明它属于一艘竖直战舰,而这艘战舰已经统计过。 - 左侧也是
X,说明它属于一艘水平战舰,同样跳过。 - 上方和左侧都没有
X,它就是一艘战舰的起点,计数加一。
例如一行连续的 XXX,只有最左侧的 X 会被计数;竖直排列时,则只有最上方的 X 会被计数。边界外没有格子,检查上方和左侧之前要先确认下标有效。
200. 岛屿数量允许连通区域弯折,可以用深度优先搜索访问整个区域;本题的直线形状和间隔条件,使我们只检查相邻格子就能完成统计。
3. 代码实现
class Solution {
public int countBattleships(char[][] board) {
int m = board.length;
int n = board[0].length;
int res = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 如果当前位置是空位,直接跳过
if (board[i][j] == '.') {
continue;
}
// 如果当前战舰的上方有战舰,说明是同一艘垂直战舰,跳过
if (i - 1 >= 0 && board[i - 1][j] == 'X') {
continue;
}
// 如果当前战舰的左方有战舰,说明是同一艘水平战舰,跳过
if (j - 1 >= 0 && board[i][j - 1] == 'X') {
continue;
}
// 当前位置既不是空位,上方和左方也都没有战舰
// 说明是一艘新战舰的起始位置,计数加1
res++;
}
}
return res;
}
}
4. 复杂度分析
- 时间复杂度:O(m * n),其中 m 是矩阵的行数,n 是矩阵的列数。
- 空间复杂度:O(1),仅使用常数级别的空间。
来源:Coding 101 原文 · 免费阅读,引用请保留出处。内容使用说明