10.leetCode419: Battleships in a Board

题目:
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”则表示有船,若为“.”则表示为空位。船只的大小可大可小,可以是单个的“X”,或者是横向多个连续的“X”、纵向多个连续的“X”(多个部分)组成的大船只。船只和船只之间一定有“.”来间隔。

思路一:找出船头的个数,即为船只的个数。船头的特征为:其左边为“.”且上边为“.”。将甲板看成一个二维向量,从左向右、从上至下搜索。需要判断的情况有三种:1.当前位置为“.”则搜索下一个位置,2.当前位置不为”.”但是左边的位置为”X”,3.当前位置不为”.”但是上边的位置为“X”,2和3说明当前”X”为船只的一部分。若以上三种情况都不是,则说明当前的“X”是船头,+1.

代码

class Solution {
    public int countBattleships(char[][] board) {
        int m = board.length;
        if(m==0)
            return 0;
        int n = board[0].length; 
        int count = 0;

        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(board[i][j] == '.' || (i>0 && board[i-1][j]=='X') || (j>0 && board[i][j-1]=='X'))
                    continue;
                count++;
            }
        }
        return count;
    }
}

注意:判断条件if(board[i][j] == '.' || (i>0 && board[i-1][j]=='X') || (j>0 && board[i][j-1]=='X'))
若分开写成3个if:
if(board[i][j] == '.' ) continue;
if(i>0 && board[i-1][j]=='X' ) continue;
if(j>0 && board[i][j-1]=='X' ) continue;
,则效率会大大降低。

思路二:使用深度优先搜索(DFS),使用一个visit来标记当前位置是否被访问过。从左向右、从上往下,判断当前位置N是否为’X’且没有被访问过,若是,则船只数加1并进行深度优先搜索。在进行深度优先搜索时,若访问节点为’X’,则visit标记为true,并再次进行DFS。否则,判断N的下一个节点。

代码

class Solution {

    public int countBattleships(char[][] board) {
        int height = board.length;
        int width = board[0].length;
        Boolean[][] visited = new Boolean[height][width];
        for(int i=0;i<height;i++){
            for(int j=0;j<width;j++)
                visited[i][j] = false;
        }
        int count = 0;
        for(int i=0;i<height;i++){
            for(int j=0;j<width;j++){
                if(board[i][j] == 'X' && visited[i][j] == false){
                    count++;
                    DFS(board,visited,i,j,height,width);
                }
            }

        }
        return count;
    }
    static void DFS(char[][] board, Boolean[][] visited, int i, int j, int height, int width){
        int[] di = {-1,0,1,0}, dj={0,-1,0,1};
        visited[i][j] = true;
        for(int k=0;k<4;k++){
            int ii = di[k]+i;
            int jj = dj[k]+j;
            if(  ii>=0 && ii<height && jj>=0 && jj<width && visited[ii][jj] ==false  &&  board[ii][jj] == 'X' )
                DFS(board,visited,ii,jj,height,width);
        }

    }
}

注意:在DFS函数中的判断句:if( ii>=0 && ii

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值