平板上的战舰

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值