题目

类型:深度优先搜索
image.png

解题思路

如果「允许扫描多次」或者「使用与输入同规模的空间」的话,做法都十分简单:

  • 允许扫描多次,但空间只能 O(1)
    • 每次遇到 X 的格子,则将 X 所在的战舰修改为 -,统计完答案后,再扫描一次,将 - 恢复为 X 即可;
  • 扫描一次,但空间允许 O(m∗n)
    • 使用一个与矩阵同等大小的辅助数组 vis 记录访问过的位置即可。

但题目要求「扫描一次」并且「空间 O(1)」
注意这里的「扫描一次」是指使用一次遍历,而非要求每个单元格仅能访问一次,注意两者区别。
上述两种做法,本质都是在战舰的首个格子进行计数,并将该战舰的所有格子进行处理,同时使用去重手段(原数组标记 或 使用辅助数组)来防止该战舰在后面遍历中被重复计数。
如果能够找到某种规律,直接判断出某个 X 格子是否为战舰开头,则不再需要其他去重手段。
当且仅当某个 X 格子的「上方」&「左方」不为 X 时,该格子为战舰首个格子,可以进行计数,同时需要注意当前当为 0(没有「上方」)和当前列为 0(没有「左方」)时的边界情况。

代码

  1. class Solution {
  2. public int countBattleships(char[][] board) {
  3. int m = board.length, n = board[0].length;
  4. int ans = 0;
  5. for (int i = 0; i < m; i++) {
  6. for (int j = 0; j < n; j++) {
  7. if (i > 0 && board[i - 1][j] == 'X') continue;
  8. if (j > 0 && board[i][j - 1] == 'X') continue;
  9. if (board[i][j] == 'X') ans++;
  10. }
  11. }
  12. return ans;
  13. }
  14. }