LeetCode:419. Battleships in a Board

来源:互联网 发布:网络盒子看电视不清晰 编辑:程序博客网 时间:2024/06/04 21:51

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:

...XXXXX...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?

题意:给定字符矩阵,其满足以下条件:
1)只存在“X” 和 ”.“。
2)X只按照行或者列进行排列
3)行列不相交。
计算X整体的个数。
分析:
算法一:DFS
找到一个未标记的X,然后利用DFS将与之连接的X全部标记,并且计数增1,然后找到下一个未标记的X,依次利用DFS标记,直到全部标记。
这个算法适用于任意形状的X的计数问题。
算法空间复杂度O(n^2),时间复杂度则为O(n^2)(邻接矩阵表示O(n^2),如果是邻接表表示则时间复杂度是O(V+e))。
代码如下:

    class Solution {    public int countBattleships(char[][] board) {        if(board==null)            return 0;        int n=board.length;        if(n==0)            return 0;        int m=board[0].length;        int count=0;        boolean[][]flag=new boolean[n][m];        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                if(board[i][j]=='X'&&!flag[i][j]){                    dfs(board,flag,i,j,n,m);                    count++;                }            }        }        return count;    }    public void dfs(char[][]board,boolean[][]flag,int i,int j,int n,int m){        flag[i][j]=true;        if(i-1>=0&&board[i-1][j]=='X'&&!flag[i-1][j])            dfs(board,flag,i-1,j,n,m);        if(j-1>=0&&board[i][j-1]=='X'&&!flag[i][j-1])            dfs(board,flag,i,j-1,n,m);        if(i+1<n&&board[i+1][j]=='X'&&!flag[i+1][j])            dfs(board,flag,i+1,j,n,m);        if(j+1<m&&board[i][j+1]=='X'&&!flag[i][j+1])            dfs(board,flag,i,j+1,n,m);         }}

算法二:
利用题目中的信息2,可以构造专门针对此题的算法:
按行扫描,如果当前节点是”X”,则判断其左边(行)和上边(列)是否仍然是”X”,如果都不是,则计数加一。
算法满足空间复杂度O(1),时间复杂度O(n^2),并且是一遍扫描。
代码如下:

class Solution {    public int countBattleships(char[][] board) {        if(board==null)            return 0;        int n=board.length;        if(n==0)            return 0;        int m=board[0].length;        int count=0;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                if(board[i][j]=='X'){                    boolean flag=false;                    if(i-1>=0&&board[i-1][j]=='X')                        flag=true;                    if(j-1>=0&&board[i][j-1]=='X')                        flag=true;                    if(!flag)                        count++;                }            }        }        return count;    } }
原创粉丝点击