LeetCode 419 - 棋盘上的战舰


文章目录
- 摘要
- 描述
- 题解答案
- 题解代码分析
- 代码解析
- 示例测试及结果
- 时间复杂度
- 空间复杂度
- 总结
摘要
这题是一个看起来挺“轻松”的矩阵题——LeetCode 419《棋盘上的战舰(Battleships in a Board)》。
你会拿到一个二维矩阵,矩阵里的 'X' 表示有战舰,. 表示空位。
要求你计算棋盘上到底有几艘战舰。
听起来像数格子,但其实隐藏着边界判断和空间优化的技巧。
这题挺有意思,因为它表面是个模拟题,但实际上是个典型的一次遍历 + 空间优化的题。
下面我们来一点点拆解这道题。

描述
给你一个大小为 m x n 的矩阵 board,每个单元格可以是战舰 'X' 或空位 '.'。
你需要返回棋盘上战舰的数量。
注意几点关键规则:
- 战舰只能是水平或垂直放置;
- 战舰之间必须至少隔一个空格(即不能相邻);
- 我们不能修改原数组;
- 尽量用 O(1) 额外空间。
示例:

输入:
board = [["X", ".", ".", "X"],[".", ".", ".", "X"],[".", ".", ".", "X"]
]
输出:2
解释:
- 第一艘战舰在第一行最左边的
X(单独的一艘); - 第二艘战舰从第一行最右边开始竖着延伸到底。
题解答案
这题其实有两种做法:
- DFS 搜索法(直觉思路,但修改原矩阵);
- 一次遍历法(更优雅,符合题目要求,不改原数据,空间 O(1))。
我们采用第二种最优方案。
核心思路是:
只统计“战舰的起点”——也就是这个格子的上面和左边都不是 'X' 的时候,才算一艘新的战舰。

题解代码分析
下面是完整的 Swift 代码实现
import Foundationclass Solution {func countBattleships(_ board: [[Character]]) -> Int {var count = 0let m = board.countlet n = board[0].countfor i in 0..<m {for j in 0..<n {// 只在遇到战舰时才考虑if board[i][j] == "X" {// 如果上方或左方也有 'X',说明这不是新舰的起点,跳过if i > 0 && board[i - 1][j] == "X" { continue }if j > 0 && board[i][j - 1] == "X" { continue }count += 1}}}return count}
}
代码解析
这一段代码看起来很简短,但逻辑非常巧妙。
-
遍历整个棋盘:
双重循环,逐个检查每个位置(i, j)。 -
判断是不是战舰:
如果当前位置是'.',直接跳过。 -
避免重复计数:
只在当前格是‘X’,且**上方和左方都不是‘X’**的时候计数。
因为如果它的上方或左方有‘X’,说明它是某艘战舰的一部分,而不是起点。 -
统计结果:
每找到一个“起点”,就加一。
这样做的最大好处是:
- 不用修改棋盘;
- 只用一次遍历;
- 空间复杂度 O(1)。
示例测试及结果
我们来验证下上面的实现:
let solution = Solution()let board1: [[Character]] = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]
]
print(solution.countBattleships(board1)) // 输出: 2let board2: [[Character]] = [[".",".","X"],[".","X","X"],[".",".","."]
]
print(solution.countBattleships(board2)) // 输出: 1let board3: [[Character]] = [[".",".","."],[".",".","."],[".",".","."]
]
print(solution.countBattleships(board3)) // 输出: 0
运行结果:
2
1
0
可以看到结果完全符合预期。
时间复杂度
- 时间复杂度:O(m × n)
我们遍历整个棋盘一次,每个格子只访问一次。
空间复杂度
- 空间复杂度:O(1)
除了几个辅助变量外,不需要额外空间。
不使用 DFS,也不需要 visited 数组。
总结
这题是个非常经典的“矩阵扫描 + 状态判断”题。
如果你第一次做可能会想到用 DFS 或 BFS 来搜索战舰连通块,但题目要求我们不能修改棋盘,这就排除了那条路。
最终,我们用“判断起点”的方式巧妙地规避了重复计算。
这是一种非常实用的技巧,常用于类似的矩阵遍历问题,比如:
- 计算“岛屿数量”;
- 判断“独立区域”;
- 识别“连续的段落”等。
