您的位置:首页 > 其它

[LeetCode]419. Battleships in a Board

2017-07-23 15:51 357 查看
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’则军舰数加1,然后从该点开始进行深度优先遍历,将代表该军舰的所有‘X’标记为访问过的状态。

public class Solution {

private int[] di = { -1, 0, 1, 0 }, dj = { 0, -1, 0, 1 };

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

public void DFS(char[][] board, boolean[][] visited, int i, int j,
int h, int w) {
int ii, jj, k;
visited[i][j] = true;
for (k = 0; k < 4; k++) {
ii = i + di[k];
jj = j + dj[k];
if (ii >= 0 && ii < h && jj >= 0 && jj < w && board[ii][jj] == 'X'
&& visited[ii][jj] == false)
DFS(board,visited,ii,jj,h,w);
}
}
}

这道题,我自己是完全没有想到图的方向,也是因为刚开始刷题,对数据结构其实都还没有特别熟悉。
其实这种题目,很明显的有点、线的关系,求不同的战艇数,也就是求图里面的最大连通子图的个数。

解法二、题目进阶要求一次遍历完,并且使用O(1)的空间复杂度,那么就不能像解法一那样再声明一个记录访问标志的二维数组。我们可以通过军舰的起点计算军舰数,所谓起点,就是指一条军舰上最左边的那个‘X’或者最上面的那个‘X’。

public class Solution {
public int countBattleships(char[][] board) {
int res = 0, height = board.length, width = board[0].length, i, j;
for (i = 0; i < height; i++)
a8b6

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

————————————————————————————————————————————

Java里的DFS的一种实现

public class DFSTest {

// 存储节点信息
private char[] vertices;

// 存储边信息(邻接矩阵)
private int[][] arcs;

// 图的节点数
private int vexnum;

// 记录节点是否已被遍历
private boolean[] visited;

// 初始化
public DFSTest(int n) {
vexnum = n;
vertices = new char
;
arcs = new int

;
visited = new boolean
;
for (int i = 0; i < vexnum; i++) {
for (int j = 0; j < vexnum; j++) {
arcs[i][j] = 0;
}
}
}

// 添加边(无向图)
public void addEdge(int i, int j) {
// 边的头尾不能为同一节点
if (i == j)return;

arcs[i][j] = 1;
arcs[j][i] = 1;
}

// 设置节点集
public void setVertices(char[] vertices) {
this.vertices = vertices;
}

// 设置节点访问标记
public void setVisited(boolean[] visited) {
this.visited = visited;
}
// 打印遍历节点
public void visit(int i){
System.out.print(vertices[i] + " ");
}

// 从第i个节点开始深度优先遍历
private void traverse(int i){
// 标记第i个节点已遍历
visited[i] = true;
// 打印当前遍历的节点
visit(i);

// 遍历邻接矩阵中第i个节点的直接联通关系
for(int j=0;j<vexnum;j++){
// 目标节点与当前节点直接联通,并且该节点还没有被访问,递归
if(arcs[i][j]==1 && visited[j]==false){
traverse(j);
}
}
}

// 图的深度优先遍历(递归)
public void DFSTraverse(){
// 初始化节点遍历标记
for (int i = 0; i < vexnum; i++) {
visited[i] = false;
}

// 从没有被遍历的节点开始深度遍历
for(int i=0;i<vexnum;i++){
if(visited[i]==false){
// 若是连通图,只会执行一次
traverse(i);
}
}
}

// 图的深度优先遍历(非递归)
public void DFSTraverse2(){
// 初始化节点遍历标记
for (int i = 0; i < vexnum; i++) {
visited[i] = false;
}

Stack<Integer> s = new Stack<Integer>();
for(int i=0;i<vexnum;i++){
if(!visited[i]){
//连通子图起始节点
s.add(i);
do{
// 出栈
int curr = s.pop();

// 如果该节点还没有被遍历,则遍历该节点并将子节点入栈
if(visited[curr]==false){
// 遍历并打印
visit(curr);
visited[curr] = true;

// 没遍历的子节点入栈
for(int j=vexnum-1; j>=0 ; j-- ){
if(arcs[curr][j]==1 && visited[j]==false){
s.add(j);
}
}
}
}while(!s.isEmpty());
}
}
}

public static void main(String[] args) {
DFSTest g = new DFSTest(9);
char[] vertices = {'A','B','C','D','E','F','G','H','I'};
g.setVertices(vertices);

g.addEdge(0, 1);
g.addEdge(0, 5);
g.addEdge(1, 0);
g.addEdge(1, 2);
g.addEdge(1, 6);
g.addEdge(1, 8);
g.addEdge(2, 1);
g.addEdge(2, 3);
g.addEdge(2, 8);
g.addEdge(3, 2);
g.addEdge(3, 4);
g.addEdge(3, 6);
g.addEdge(3, 7);
g.addEdge(3, 8);
g.addEdge(4, 3);
g.addEdge(4, 5);
g.addEdge(4, 7);
g.addEdge(5, 0);
g.addEdge(5, 4);
g.addEdge(5, 6);
g.addEdge(6, 1);
g.addEdge(6, 3);
g.addEdge(6, 5);
g.addEdge(6, 7);
g.addEdge(7, 3);
g.addEdge(7, 4);
g.addEdge(7, 6);
g.addEdge(8, 1);
g.addEdge(8, 2);
g.addEdge(8, 3);

System.out.print("深度优先遍历(递归):");
g.DFSTraverse();

System.out.println();
System.out.print("深度优先遍历(非递归):");
g.DFSTraverse2();
}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: