Battleships in a Board
Problem
Given an m x n matrix board where each cell is a battleship 'X' or empty '.', return the number of the battleships on board.
Battleships can only be placed horizontally or vertically on board. In other words, they can only be made of the shape 1 x k (1 row, k columns) or k x 1 (k rows, 1 column), where k can be of any size. At least one horizontal or vertical cell separates between two battleships (i.e., there are no adjacent battleships).
Examples
Example 1:

Input:
board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]]
Output:
2
Example 2:
Input:
board = [["."]]
Output:
0
Solution
Method 1 – One Pass Counting
Intuition
A battleship is represented by consecutive 'X's horizontally or vertically, and ships are separated by at least one '.' cell. We only count the top-left cell of each ship (a cell that is 'X' and has no 'X' above or to the left).
Approach
- Iterate through each cell in the board.
- If the cell is 'X' and there is no 'X' directly above or to the left, increment the count.
- Return the total count after scanning the board.
Code
C++
class Solution {
public:
int countBattleships(vector<vector<char>>& board) {
int m = board.size(), n = board[0].size(), ans = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 'X' && (i == 0 || board[i-1][j] != 'X') && (j == 0 || board[i][j-1] != 'X')) {
ans++;
}
}
}
return ans;
}
};
Go
func countBattleships(board [][]byte) int {
m, n := len(board), len(board[0])
ans := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if board[i][j] == 'X' && (i == 0 || board[i-1][j] != 'X') && (j == 0 || board[i][j-1] != 'X') {
ans++
}
}
}
return ans
}
Java
class Solution {
public int countBattleships(char[][] board) {
int m = board.length, n = board[0].length, ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'X' && (i == 0 || board[i-1][j] != 'X') && (j == 0 || board[i][j-1] != 'X')) {
ans++;
}
}
}
return ans;
}
}
Kotlin
class Solution {
fun countBattleships(board: Array<CharArray>): Int {
val m = board.size
val n = board[0].size
var ans = 0
for (i in 0 until m) {
for (j in 0 until n) {
if (board[i][j] == 'X' && (i == 0 || board[i-1][j] != 'X') && (j == 0 || board[i][j-1] != 'X')) {
ans++
}
}
}
return ans
}
}
Python
class Solution:
def countBattleships(self, board: list[list[str]]) -> int:
m, n = len(board), len(board[0])
ans = 0
for i in range(m):
for j in range(n):
if board[i][j] == 'X' and (i == 0 or board[i-1][j] != 'X') and (j == 0 or board[i][j-1] != 'X'):
ans += 1
return ans
Rust
impl Solution {
pub fn count_battleships(board: Vec<Vec<char>>) -> i32 {
let m = board.len();
let n = board[0].len();
let mut ans = 0;
for i in 0..m {
for j in 0..n {
if board[i][j] == 'X' && (i == 0 || board[i-1][j] != 'X') && (j == 0 || board[i][j-1] != 'X') {
ans += 1;
}
}
}
ans
}
}
TypeScript
class Solution {
countBattleships(board: string[][]): number {
const m = board.length, n = board[0].length;
let ans = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (board[i][j] === 'X' && (i === 0 || board[i-1][j] !== 'X') && (j === 0 || board[i][j-1] !== 'X')) {
ans++;
}
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(m * n), wheremandnare the dimensions of the board, since each cell is visited once. - 🧺 Space complexity:
O(1), as only a few variables are used for counting.
Method 2 – DFS Marking
Intuition
We can use DFS to mark all cells of a battleship as visited. For each unvisited 'X', start a DFS to mark the entire ship, and increment the count.
Approach
- Iterate through each cell in the board.
- If the cell is 'X', start a DFS to mark all connected 'X's as visited (change to '.').
- Increment the count for each DFS call.
- Return the total count after scanning the board.
Code
C++
class Solution {
public:
void dfs(vector<vector<char>>& board, int i, int j) {
int m = board.size(), n = board[0].size();
if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'X') return;
board[i][j] = '.';
dfs(board, i+1, j);
dfs(board, i-1, j);
dfs(board, i, j+1);
dfs(board, i, j-1);
}
int countBattleships(vector<vector<char>>& board) {
int m = board.size(), n = board[0].size(), ans = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == 'X') {
dfs(board, i, j);
ans++;
}
}
}
return ans;
}
};
Go
func countBattleships(board [][]byte) int {
m, n := len(board), len(board[0])
var dfs func(int, int)
dfs = func(i, j int) {
if i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'X' {
return
}
board[i][j] = '.'
dfs(i+1, j)
dfs(i-1, j)
dfs(i, j+1)
dfs(i, j-1)
}
ans := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if board[i][j] == 'X' {
dfs(i, j)
ans++
}
}
}
return ans
}
Java
class Solution {
public int countBattleships(char[][] board) {
int m = board.length, n = board[0].length, ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'X') {
dfs(board, i, j);
ans++;
}
}
}
return ans;
}
void dfs(char[][] board, int i, int j) {
int m = board.length, n = board[0].length;
if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'X') return;
board[i][j] = '.';
dfs(board, i+1, j);
dfs(board, i-1, j);
dfs(board, i, j+1);
dfs(board, i, j-1);
}
}
Kotlin
class Solution {
fun countBattleships(board: Array<CharArray>): Int {
val m = board.size
val n = board[0].size
fun dfs(i: Int, j: Int) {
if (i !in 0 until m || j !in 0 until n || board[i][j] != 'X') return
board[i][j] = '.'
dfs(i+1, j)
dfs(i-1, j)
dfs(i, j+1)
dfs(i, j-1)
}
var ans = 0
for (i in 0 until m) {
for (j in 0 until n) {
if (board[i][j] == 'X') {
dfs(i, j)
ans++
}
}
}
return ans
}
}
Python
class Solution:
def countBattleships(self, board: list[list[str]]) -> int:
m, n = len(board), len(board[0])
def dfs(i, j):
if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != 'X':
return
board[i][j] = '.'
dfs(i+1, j)
dfs(i-1, j)
dfs(i, j+1)
dfs(i, j-1)
ans = 0
for i in range(m):
for j in range(n):
if board[i][j] == 'X':
dfs(i, j)
ans += 1
return ans
Rust
impl Solution {
pub fn count_battleships(board: &mut Vec<Vec<char>>) -> i32 {
fn dfs(board: &mut Vec<Vec<char>>, i: i32, j: i32) {
let m = board.len() as i32;
let n = board[0].len() as i32;
if i < 0 || i >= m || j < 0 || j >= n || board[i as usize][j as usize] != 'X' {
return;
}
board[i as usize][j as usize] = '.';
dfs(board, i+1, j);
dfs(board, i-1, j);
dfs(board, i, j+1);
dfs(board, i, j-1);
}
let m = board.len();
let n = board[0].len();
let mut ans = 0;
for i in 0..m {
for j in 0..n {
if board[i][j] == 'X' {
dfs(board, i as i32, j as i32);
ans += 1;
}
}
}
ans
}
}
TypeScript
class Solution {
countBattleships(board: string[][]): number {
const m = board.length, n = board[0].length;
function dfs(i: number, j: number) {
if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] !== 'X') return;
board[i][j] = '.';
dfs(i+1, j);
dfs(i-1, j);
dfs(i, j+1);
dfs(i, j-1);
}
let ans = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (board[i][j] === 'X') {
dfs(i, j);
ans++;
}
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(m * n), since each cell is visited at most once. - 🧺 Space complexity:
O(m * n)in the worst case due to recursion stack.