Given an 2D board, count how many 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) orNx1
(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 ...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?
这个题和前面某一个类似,求那个独立岛屿的数量。我看了以后,感觉和上一题417的思路特别像。(我看了网友的解答以后,发现自己的方法蠢酷了,又臭又长,不感兴趣的朋友,请直接跳到方法二)
方法一:
BFS搜索,和上面一题一样的,从左上角开始进行BFS搜索。使用循环和queue,boolean[][],搜索没有ship的格子“.”,然后把这个格子放到queue中,对应位置标记true,取出这个格子,继续循环,直到queue为空。
但是,一旦发现有ship的格子“X”,总和++,然后跳转到另一个函数,对这个格子四个方向的所有“X”格子进行搜索,这时候同样有另一个queue和循环,保证将这一个ship的所有格子都搜索到,并对应位置标记为true。(因为如果不一次性把当前ship对应的所有x找到,那么在后面的搜索中,可能会搜索到这个x,那就不知道这个x对应的ship到底有没有被搜索到。)
最后,返回总和即可。
由于BFS的时候,对于一个格子,搜索的是四个方向的,因此复杂度大约是O(4N),这个方法效率比较差,只打败了1.03%,代码的重用性也很差(我自己想的),不推荐。代码如下:
public class Solution {
char[][] board;
int nHeight;
int nWidth;
boolean[][] bExpl;
int nTotal;
Queue<int[]> queCommon;
public int countBattleships(char[][] board) {
if (board.length == 0||board==null || board[0].length==0) {
return 0;
}
this.board = board;
nHeight = board.length;
nWidth = board[0].length;
bExpl = new boolean[nHeight][nWidth];
queCommon = new LinkedList<int[]>();
// init
bExpl[0][0] = true;
if (board[0][0] == '.') {
queCommon.add(new int[] { 0, 0 });
} else {
nTotal++;
findShip(new int[] { 0, 0 });
}
//explore the common point
while (queCommon.size() > 0) {
int[] nArrCur = queCommon.poll();
// judge the current grid x or .
explore(nArrCur, queCommon);
}
return nTotal;
}
private boolean isBeyond(int x, int y) {
return x >= 0 && y >= 0 && x < nHeight && y < nWidth ? true : false;
}
private void explore(int[] n, Queue<int[]> q) {
int x = n[0];
int y = n[1];
if (isBeyond(x, y - 1)) {
tagNewPoint(x, y - 1, q);
}
if (isBeyond(x, y + 1)) {
tagNewPoint(x, y + 1, q);
}
if (isBeyond(x - 1, y)) {
tagNewPoint(x - 1, y, q);
}
if (isBeyond(x + 1, y)) {
tagNewPoint(x + 1, y, q);
}
}
private void exploreShip(int[] n, Queue<int[]> q) {
int x = n[0];
int y = n[1];
if (isBeyond(x, y - 1)) {
tagNewShip(x, y - 1, q);
}
if (isBeyond(x, y + 1)) {
tagNewShip(x, y + 1, q);
}
if (isBeyond(x - 1, y)) {
tagNewShip(x - 1, y, q);
}
if (isBeyond(x + 1, y)) {
tagNewShip(x + 1, y, q);
}
}
private void findShip(int[] n) {
Queue<int[]> queShip = new LinkedList<int[]>();
queShip.add(n);
while (queShip.size() > 0) {
int[] nArrCur = queShip.poll();
// find all nearby ship
exploreShip(nArrCur, queShip);
}
}
private void tagNewPoint(int x, int y, Queue<int[]> q) {
if (bExpl[x][y] == false) {
bExpl[x][y] = true;
int[] nn = { x, y };
if (board[x][y] == '.') {
q.add(nn);
} else {
nTotal++;
//when meets the ship, and find the whole ship once
findShip(nn);
}
}
}
private void tagNewShip(int x, int y, Queue<int[]> q) {
if (bExpl[x][y] == false) {
bExpl[x][y] = true;
int[] nn = { x, y };
if (board[x][y] == 'X') {
q.add(nn);
} else {
queCommon.add(nn);
}
}
}
}
方法二:
这个方法代码量也少,原理也简单,网友还是机制。
它利用了这个题目的特性,根据题意,任意两个ships都是隔开的;也就是说,不可能存在一个ship,四面相邻另一个ship;再换句话说,由于所有的ship不是横着就是竖着的,所有任意一个ship的左上角第一个格子的上面和左边必然相邻的不是ship,我们只用数一数这样的格子有几个,就知道有几个ship了。
另外,这个方法需要注意的是:在当前格子位于边缘的时候,左边和上面的格子index值为-1,如果这时候再直接取值的话,会出现数组超界的错误。
这个方法大概的复杂度应该是O(2N),代码如下:
public class Solution {
public int countBattleships(char[][] board) {
if (board == null) {
return 0;
}
int nTotal = 0;
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 'X') {
boolean bI = i == 0 ? true : false;
boolean bJ = j == 0 ? true : false;
if (!bI) {
bI = board[i - 1][j] == '.' ? true : false;
}
if (!bJ) {
bJ = board[i][j - 1] == '.' ? true : false;
}
if (bI && bJ) {
nTotal++;
}
}
}
}
return nTotal;
}
}