Given an 2D board, count how many different battleships are in it. The battleships are represented with 'X'
s, empty slots are represented with '.'
s. You may assume the following rules:
1xN
(1 row, N columns) orNx1
(N rows, 1 column), where N can be of any size. Example:
X..X ...X ...XIn the above board there are 2 battleships.
Invalid Example:
...X XXXX ...XThis is an invalid board that you will not receive - as battleships will always have a cell separating between them.
Follow up:
Could you do it in one-pass, using only O(1) extra memory and without modifying the value of the board?
题目大意:水平方向或者竖直方向上的'X'集合算一条军舰,不能拐弯,不会出现两条军舰挨着的情况。
思路:
解法一、一种解法是深度优先遍历,用两层循环对所有位置进行遍历,遇到没被访问过的‘X’则军舰数加1,然后从该点开始进行深度优先遍历,将代表该军舰的所有‘X’标记为访问过的状态。
解法二、题目进阶要求一次遍历完,并且使用O(1)的空间复杂度,那么就不能像解法一那样再声明一个记录访问标志的二维数组。我们可以通过军舰的起点计算军舰数,所谓起点,就是指一条军舰上最左边的那个‘X’或者最上面的那个‘X’。
解法一:DFS(6ms,beats 12.59%)
public class Solution {
private int[] di = { -1, 0, 1, 0 }, dj = { 0, -1, 0, 1 };
public int countBattleships(char[][] board) {
int res = 0, height = board.length, width = board[0].length, i, j, m, n;
boolean[][] visited = new boolean[height][width];
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
visited[i][j] = false;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++) {
if (board[i][j] == 'X' && visited[i][j] == false) {
res++;
DFS(board, visited, i, j, height, width);
}
}
return res;
}
public void DFS(char[][] board, boolean[][] visited, int i, int j,
int h, int w) {
int ii, jj, k;
visited[i][j] = true;
for (k = 0; k < 4; k++) {
ii = i + di[k];
jj = j + dj[k];
if (ii >= 0 && ii < h && jj >= 0 && jj < w && board[ii][jj] == 'X'
&& visited[ii][jj] == false)
DFS(board,visited,ii,jj,h,w);
}
}
}
解法二:计算军舰起点数(3ms,beats 93.6%)
public class Solution {
public int countBattleships(char[][] board) {
int res = 0, height = board.length, width = board[0].length, i, j;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++) {
if (board[i][j] == '.' || (i > 0 && board[i - 1][j] == 'X')
|| j > 0 && board[i][j - 1] == 'X')
continue;
res++;
}
return res;
}
}