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
- You receive a valid board, made of only battleships or empty slots.
- Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape 1xN (1 row, N columns) or Nx1 (N rows, 1 column), where N can be of any size.
- At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
X..X
…X
…X
In the above board there are 2 battleships.
Invalid Example:
…X
XXXX
…X
This is not a valid board - as battleships will always have a cell separating between them.
Your algorithm should not modify the value of the board.
看到这题目,我就直接意识到是用DFS,因为这题目有点像是迷宫类型的题目,只不过它并不是要找路径,而是要找到矩阵里所有的船的数目。
所以思路就是
1.设置一个与矩阵同样大小的布尔数组visited,用于表示某一个位置是否已经被访问过
2遍历矩阵的每一个位置,如果是标志船的’X’并且该位置没有被访问过,就增加船的数目,然后通过DFS算法把整个船找到,并且把船的所有位置都设为已访问。
3.最后返回找到的船的数目。
虽然思路是有的,但是我太久没有写DFS,所以最后自己没能实现出来,是查看了大牛们的实现,再自己重新打了一遍,(⊙﹏⊙)b。
除了用DFS,还有一种更为聪明的办法,就是只找表示船头的元素个数,下面来讲讲这种解法。
这种思路利用了船只能在水平方向或是垂直方向上延伸,因此船的最左边(水平方向)或是最上边(垂直方向)的元素就很特殊,因为它的左边(水平方向)或是上边(垂直方向)的元素会是’.’,而对于船中部的元素,它们的左边或是上边的元素肯定有一个会是’X’。
利用这点,我们可以遍历矩阵每一个元素,当符合是船头元素时,就增加船的个数,否则继续遍历下一个元素,最后返回找到的船的个数即可。
class Solution {
private:
vector<vector<bool>> visited;
// row size and column size
int rsize,csize;
int direc[4][2] = {{1, 0}, {0,1}, {-1, 0}, {0, -1}};
public:
void dfs(vector<vector<char>>& board, int i, int j) {
if (i < 0 || i >= rsize || j < 0 || j >= csize || board[i][j] == '.' || visited[i][j])
return ;
visited[i][j] = true;
for (int d = 0; d < 4; d++) {
dfs(board, i + direc[d][0], j + direc[d][1]);
}
}
int countBattleships(vector<vector<char>>& board) {
if (board.empty())
return 0;
rsize = board.size();
csize = board[0].size();
visited.resize(rsize, vector<bool>(csize, false));
int count = 0;
for (int i = 0; i < rsize; i++) {
for (int j = 0; j < csize; j++) {
if (board[i][j] == 'X' && !visited[i][j]) {
count++;
dfs(board, i, j);
}
}
}
return count;
}
};
class Solution {
public:
int countBattleships(vector<vector<char>>& board) {
if (board.empty())
return 0;
int rsize = board.size();
int csize = board[0].size();
int count = 0;
for (int i = 0; i < rsize; i++)
for (int j = 0; j < csize; j++)
if (board[i][j] == 'X' && (i == 0 || board[i - 1][j] == '.') && (j == 0 || board[i][j - 1] == '.'))
count++;
return count;
}
};
通过这道题,小小地复习了一下DFS,还得花时间去重新好好复习一下,另外那个找船头的方式确实很巧妙,好佩服能想到这种方式的大牛。
抽了点时间填了一个坑!之前两天都有填坑,但是着实腾不出时间出来写报告,之后会补上的!明天继续加油!