跳到主要内容

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 原文 · 免费阅读,引用请保留出处。内容使用说明