题目
类型:深度优先搜索
解题思路
如果「允许扫描多次」或者「使用与输入同规模的空间」的话,做法都十分简单:
- 允许扫描多次,但空间只能 O(1)
- 每次遇到 X 的格子,则将 X 所在的战舰修改为 -,统计完答案后,再扫描一次,将 - 恢复为 X 即可;
- 扫描一次,但空间允许 O(m∗n)
- 使用一个与矩阵同等大小的辅助数组 vis 记录访问过的位置即可。
但题目要求「扫描一次」并且「空间 O(1)」
注意这里的「扫描一次」是指使用一次遍历,而非要求每个单元格仅能访问一次,注意两者区别。
上述两种做法,本质都是在战舰的首个格子进行计数,并将该战舰的所有格子进行处理,同时使用去重手段(原数组标记 或 使用辅助数组)来防止该战舰在后面遍历中被重复计数。
如果能够找到某种规律,直接判断出某个 X 格子是否为战舰开头,则不再需要其他去重手段。
当且仅当某个 X 格子的「上方」&「左方」不为 X 时,该格子为战舰首个格子,可以进行计数,同时需要注意当前当为 0(没有「上方」)和当前列为 0(没有「左方」)时的边界情况。
代码
class Solution {
public int countBattleships(char[][] board) {
int m = board.length, n = board[0].length;
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i > 0 && board[i - 1][j] == 'X') continue;
if (j > 0 && board[i][j - 1] == 'X') continue;
if (board[i][j] == 'X') ans++;
}
}
return ans;
}
}