LeetCode原题:Battleships in a Board
Description:
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) 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 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)表示,他们只能够垂直或者水平放置,且会被由‘.’构成的水平或垂直空间隔开,让求战舰数量。
小编读完题后马上就开始码代码:
如下:
错误的解法:
//解法一:
/*
* 每次找到船头,先计数,然后递归改变此船的值为'.',即变为已搜寻
* 然后再找船头,如此循环直到全部遍历完。
* */
class Solution {
public int countBattleships(char[][] board) {
if(board == null || board.length <= 0 || board[0].length <= 0)
return 0;
int count = 0;
for(int i = 0 ; i < board.length ; i ++){
for(int j = 0 ; j < board[0].length ; j ++){
if(board[i][j] == 'X'){
replace(board, i, j);
++ count;
}
}
}
return count;
}
//将该船已知的为X的位置替换为.
public void replace(char[][] board , int x, int y){
if(board[x][y] == 'X')
board[x][y] = '.';//为1的地方置0
else
return ;//为0则返回
if(x + 1 < board.length)
replace(board, x + 1, y);
if(y + 1 < board[0].length)
replace(board, x, y + 1);
}
}
写完再回头看题目要求,惊呆了,因为题目中有这么一句话:
Could you do it in one-pass, using only O(1) extra memory and without modifying the value of the board?
也就是说不能改变原数组的值(虽然笔者发现解法一也是能够Accepted的)。那么我们采用以下的一种比较巧妙的方法。
正解:
就是在遍历时判断元素是不是船头,因为船只能水平或垂直放置,所以船头的上、下(如果存在的话)都应该是‘.’(明显可以排除船身和船尾)。
船部分 | 为’.’的方位 |
---|---|
船头(水平) | 左、上、下 <——– |
船身(水平) | 上、下 |
船尾(水平) | 右、上、下 |
船头(垂直) | 左、上、右 <——– |
船身(垂直) | 左、右 |
船尾(垂直) | 右、上、左 |
由表知,这种方法很容易判断船只的数量。
所以,原问题转化为求船头数量。
附代码:
class Solution {
public int countBattleships(char[][] board) {
if(board == null || board.length <= 0 || board[0].length <= 0)
return 0;
int cnt = 0;
for(int i = 0 ; i < board.length ; i ++){
for(int j = 0 ; j < board[0].length ; j ++){
if(board[i][j] == 'X'){
if((i-1 < 0 || board[i-1][j] == '.')&&(j-1 < 0 || board[i][j-1] == '.'))
++cnt;
}
}
}
return cnt;
}
}